pari-2.5.5/0000755000175000017500000000000012212611624011101 5ustar billbillpari-2.5.5/README-git0000644000175000017500000001032012147140046012540 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.5.5/AUTHORS0000644000175000017500000001131012147140046012147 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 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 CW = Carl Witty DB = Dominique Bernardi DCa= David Carlisle DC = Dan Christensen DE = Denis Excoffier DF = David Ford DS = Denis Simon 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 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 PH = Paul Howarth 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 VL = Vincent Lefevre XR = Xavier Roblot YU = Yoshiaki Uchikawa pari-2.5.5/CHANGES-2.40000644000175000017500000025507212147140046012412 0ustar billbill# $Id$ Bug numbers refer to the BTS at http://pari.math.u-bordeaux.fr/Bugs/ Done for version 2.5.0 (released 31/05/2011): Fixed BA 1- DESTDIR did not work. [#1194] BA 2- Improve Darwin shared library support. LGr 3- bnfinit -> 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 ZX_cmp0 -> ZX_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.5.5/Odos/0000755000175000017500000000000012212611624012005 5ustar billbillpari-2.5.5/Odos/pariCE.h0000644000175000017500000000051312147140046013322 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.5.5/Odos/pariCE.c0000644000175000017500000000706112147140046013322 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.5.5/Odos/pariinl.h0000644000175000017500000000040012147140046013610 0ustar billbill/* This file contains declarations/definitions of functions that * _can_ be inlined. */ /* $Id$ */ #ifndef WINCE # include "../src/kernel/ix86/level0.h" #else # include "../src/kernel/none/level0.h" #endif #include "../src/kernel/none/level1.h" pari-2.5.5/Odos/acro.c0000644000175000017500000000062412147140046013101 0ustar billbill#include #include int main(char **argv, int argc) { HKEY handle; const char *key = "AcroExch.Document\\shell\\open\\command"; const long SZ = 512; char str[SZ]; long L = SZ, t, i; (void)RegOpenKeyEx(HKEY_CLASSES_ROOT, key, 0, KEY_READ, &handle); (void)RegQueryValueEx(handle, NULL, 0, &t, (LPBYTE)str, &L); RegCloseKey(handle); printf("%s\n", str); exit(0); } pari-2.5.5/Odos/makegprc0000644000175000017500000000073412147140046013527 0ustar billbillprint "Creating a .gprc\n"; $d = join(' ', @ARGV); $d =~ s,\\,/,g; $od= $d; $d =~ s/ /\\\\ /g; if (-f ".gprc") { print "Renaming existing .gprc to .gprc.bak\n"; rename(".gprc", ".gprc.bak"); } open(OUT, "> .gprc"); print OUT << "EOT"; colors = \"boldfg\" datadir = \"$od\" help = \"$d/perl.exe $d/gphelp -cu 6\" prettyprinter = \"$d/perl.exe $d/tex2mail -TeX -noindent -ragged -by_par\" prompt = \"(%H:%M) gp > \" EOT ; close(OUT); print "Done.\n"; sleep(2); pari-2.5.5/Odos/paricfg.h0000644000175000017500000000343212212162704013573 0ustar billbill/* This file extracted by Configure. */ #ifndef __CONFIG_H__ #define __CONFIG_H__ #ifdef _MSC_VER /* Bill Daly: avoid spurious Warnings from MSVC */ # pragma warning(disable: 4013 4018 4146 4244 4761) #endif #define GPDATADIR "/pari/data" #define SHELL_Q '"' #define DL_DFLT_NAME "libpari.dll" #define PARIVERSION "GP/PARI CALCULATOR Version 2.5.5 (development git-d41178d)" #if defined(__EMX__) # define PARIINFO "ix86 running EMX (ix86 kernel) 32-bit version" #endif #if defined(WINCE) # define PARIINFO "Windows CE 32-bit version" #endif #if !defined(PARIINFO) # define PARIINFO "ix86 running Windows 3.2 (ix86 kernel) 32-bit version" #endif #define PARI_VERSION_CODE 132357 #define PARI_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) #define PARI_VERSION_SHIFT 8 #define PARI_VCSVERSION "git-d41178d" #define PARI_DOUBLE_FORMAT 1 #ifdef _MSC_VER /* MSVC inline directive */ # define INLINE __inline #endif /* Location of GNU gzip program, enables reading of .Z and .gz files. */ #ifndef WINCE # define GNUZCAT # define ZCAT "gzip -d -c" #endif #ifdef __EMX__ # define STACK_CHECK # define READLINE # define HAS_RL_MESSAGE # define CPPFunction_defined /* in readline 1, no arguments for rl_refresh_line() */ # define RL_REFRESH_LINE_OLDPROTO #endif #ifdef __MINGW32__ # define READLINE "4.0" # define HAS_COMPLETION_APPEND_CHAR # define HAS_RL_SAVE_PROMPT # define HAS_RL_MESSAGE # define CPPFunction_defined #endif #if defined(__EMX__) || defined(_WIN32) # define HAS_ISATTY #endif /* No exp2, log2 in libc */ #define NOEXP2 #if !defined(WINCE) && !(defined(_WIN32) && defined(_MSC_VER)) /* Timings: Don't use times because of the HZ / CLK_TCK confusion. */ # define USE_FTIME 1 # define HAS_STRFTIME #endif #if defined(_WIN32) && defined(_MSC_VER) # define HAS_STAT #endif #endif pari-2.5.5/Odos/README.MSVC0000644000175000017500000000614112147140046013440 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.5.5/Odos/pari.nsi0000644000175000017500000001143712147140046013463 0ustar billbill!include "MUI.nsh" Name "PARI 2.5 (STABLE)" !define dll "libpari-gmp.dll" ;--No need to modify things below -- !define top ".." !define objdir "${top}\Ocygwin-i686" AutoCloseWindow false OutFile "Pari.exe" InstallDir "$PROGRAMFILES\PARI" InstallDirRegKey HKLM "Software\PARI" "" !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\PARI" Section "pari (required)" SecCopy SetOutPath "$INSTDIR" File /oname=gp.exe "${objdir}\gp-dyn.exe" File "makegprc" File "${top}\misc\tex2mail" File "${objdir}\${dll}" File "\cygwin\bin\cyggmp-3.dll" File "\cygwin\bin\cygncurses-9.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" WriteRegStr HKCU "Software\PARI" "" $INSTDIR WriteRegStr HKLM ${uninst} "DisplayName" "PARI (remove only)" WriteRegStr HKLM ${uninst} "UninstallString" '"$INSTDIR\uninstall.exe"' WriteUninstaller "$INSTDIR\Uninstall.exe" SetOutPath "$INSTDIR" ExecWait "perl makegprc $INSTDIR" Delete "$INSTDIR\makegprc" SectionEnd Section "Galois files" SecGAL SetOutPath "$INSTDIR\galdata" File "${top}\data\galdata\*" SectionEnd Section "documentation" SecDOC SetOutPath "$INSTDIR" File "${top}\doc\gphelp" SetOutPath $INSTDIR\doc File "acro.exe" 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\PARI" 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_GAL ${LANG_ENGLISH} "Install Galois data files (degree > 7)." 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 ${SecGAL} $(DESC_GAL) !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\cyggmp-3.dll" Delete "$INSTDIR\cygncurses-9.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\galdata" DeleteRegKey HKLM ${uninst} DeleteRegKey /ifempty HKLM "Software\PARI" RMDir /r "$SMPROGRAMS\PARI" Delete "$DESKTOP\PARI.lnk" RMDir "$INSTDIR" SectionEnd pari-2.5.5/INSTALL0000644000175000017500000000150611636712103012137 0ustar billbillAssuming your system is a fairly standard Unix, you can quickly build/test GP in the following way: a) look at MACHINES to see if anything funny applies to your configuration b) ./Configure ( --prefix=/exotic/dir/name if desired. Default is /usr/local. ) c) make all, make bench d) make install if desired e) copy misc/gprc.dft to /etc/gprc [sitewide] or $HOME/.gprc [personal] All documentation can be found in directory doc. Compile and read doc/INSTALL.tex (e.g cd doc; tex INSTALL; xdvi INSTALL) for more detailed installation instructions. P.S: data for the polgalois() function (12 > degree > 7) is provided in a separate archive galdata.tgz, which you have to fetch separately. P.S2: the same procedure should work on Windows 95/98/Me/XP/NT: with the Cygwin package OS/2 : with EMX, GNU tools, and pdksh pari-2.5.5/COPYING0000644000175000017500000004325412141040641012140 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.5.5/src/0000755000175000017500000000000012212611624011670 5ustar billbillpari-2.5.5/src/basemath/0000755000175000017500000000000012212611624013454 5ustar billbillpari-2.5.5/src/basemath/FpX.c0000644000175000017500000010624312147140046014325 0ustar billbill/* $Id$ 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 */ /***********************************************************************/ /** **/ /** 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. */ /* 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), i; GEN z = cgetg(l-1, t_POL), a0, z0; z[1] = evalsigne(1) | evalvarn(0); a0 = a + l-1; z0 = z + l-2; *z0 = *a0--; for (i=l-3; i>1; i--) /* z[i] = (a[i+1] + x*z[i+1]) % p */ { GEN t = addii(gel(a0--,0), Fp_mul(x, gel(z0--,0), p)); *z0 = (long)t; } if (r) *r = addii(gel(a0,0), Fp_mul(x, gel(z0,0), 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) { GEN m = cgetg(3, t_MAT); gel(m,1) = mkcol2(pol_1(v),pol_0(v)); gel(m,2) = mkcol2(pol_0(v),pol_1(v)); return m; } 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(x,-n),RgX_shift(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(y1,-k), RgX_shift(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=p[2]; M = FlxM_to_ZXM(Flx_halfgcd(ZX_to_Flx(x, pp),ZX_to_Flx(y, pp), pp)); } else { 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 = p[2]; (void)new_chunk((lg(x) + lg(y)) << 2); /* scratch space */ x = ZX_to_Flx(x, pp); y = ZX_to_Flx(y, pp); 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=p[2]; x = ZX_to_Flx(x, pp); y = ZX_to_Flx(y, pp); 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 = modii(addii(mulii(p1,r), gel(x,j)),p); } 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); } 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; } /***********************************************************************/ /** **/ /** Montgomery reduction **/ /** **/ /***********************************************************************/ static GEN FpX_invMontgomery_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_mulspec(GEN a, GEN b, GEN p, long na, long nb) { return FpX_red(ZX_mulspec(a, b, na, nb), p); } static GEN FpX_invMontgomery_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 && 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_invMontgomery(GEN T, GEN p) { pari_sp ltop = avma; long l = lg(T); GEN r; if (l<5) return pol_0(T[1]); if (l<=FpX_INVMONTGOMERY_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_invMontgomery_basecase(T, p); r = FpX_Fp_mul(r, ci, p); } else r = FpX_invMontgomery_basecase(T, p); } else r = FpX_invMontgomery_Newton(T, p); return gerepileupto(ltop, r); } /* Compute x mod T where degpol(x)<=2*(degpol(T)-1) i.e. lgpol(x)<2*lgpol(T)-2 * and mg is the Montgomery inverse of T. */ GEN FpX_rem_Montgomery(GEN x, GEN mg, GEN T, GEN p) { pari_sp ltop=avma; GEN z; long l = lgpol(x); long lt = degpol(T); /*We discard the leading term*/ long ld, lm, lT, lmg; if (l<=lt) return ZX_copy(x); ld = l-lt; lm = minss(ld, lgpol(mg)); lT = ZX_lgrenormalizespec(T+2,lt); lmg = ZX_lgrenormalizespec(mg+2,lm); z = FpX_recipspec(x+2+lt,ld,ld); /* z = rec(x) lz<=ld*/ z = FpX_mulspec(z+2,mg+2,p,lgpol(z),lmg); /* z = rec(x) * mg lz<=ld+lm*/ z = FpX_recipspec(z+2,minss(ld,lgpol(z)),ld);/* z = rec (rec(x) * mg) lz<=ld*/ z = FpX_mulspec(z+2,T+2,p,lgpol(z),lT); /* z *= pol lz<=ld+lt*/ z = FpX_subspec(x+2,z+2,p,lt,minss(lt,lgpol(z)));/* z = x - z lz<=lt */ z[1] = x[1]; return gerepileupto(ltop, z); } GEN FpX_rem(GEN x, GEN y, GEN p) { long dy = degpol(y), dx = degpol(x), d = dx-dy; if (d < 0) return FpX_red(x,p); if (d+3 < FpX_REM_MONTGOMERY_LIMIT || d>dy-2) return FpX_divrem(x,y,p,ONLY_REM); else { pari_sp av=avma; GEN mg = FpX_invMontgomery(y, p); return gerepileupto(av, FpX_rem_Montgomery(x, mg, y, p)); } } /***********************************************************************/ /** **/ /** 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 T, GEN p) { GEN V, z = FpX_extgcd(T, 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(gdiver); 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)); } static GEN FpXQ_mul_mg(GEN x,GEN y,GEN mg,GEN T,GEN p) { GEN z = FpX_mul(x,y,p); if (lg(T) > lg(z)) return z; return FpX_rem_Montgomery(z, mg, T, p); } /* Square of y in Z/pZ[X]/(T), as t_VECSMALL. */ static GEN FpXQ_sqr_mg(GEN y,GEN mg,GEN T,GEN p) { GEN z = FpX_sqr(y,p); if (lg(T) > lg(z)) return z; return FpX_rem_Montgomery(z, mg, T, p); } typedef struct { GEN T, p, mg; } FpX_muldata; static GEN _sqr_montgomery(void *data, GEN x) { FpX_muldata *D = (FpX_muldata*)data; return FpXQ_sqr_mg(x,D->mg, D->T, D->p); } static GEN _mul_montgomery(void *data, GEN x, GEN y) { FpX_muldata *D = (FpX_muldata*)data; return FpXQ_mul_mg(x,y,D->mg, D->T, D->p); } static GEN _FpXQ_sqr(void *data, GEN x) { FpX_muldata *D = (FpX_muldata*)data; return FpXQ_sqr(x, D->T, D->p); } static GEN _FpXQ_mul(void *data, GEN x, GEN y) { FpX_muldata *D = (FpX_muldata*)data; return FpXQ_mul(x,y, D->T, D->p); } /* 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) { FpX_muldata 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 = p[2]; T = ZX_to_Flx(T, pp); x = ZX_to_Flx(x, pp); y = Flx_to_ZX( Flxq_pow(x, n, T, pp) ); } else { long lx = lgpol(x), lT = lgpol(T); D.T = T; D.p = p; if (s < 0) x = FpXQ_inv(x,T,p); if (lT+2>FpX_POW_MONTGOMERY_LIMIT) { D.mg = FpX_invMontgomery(T,p); if (lx>=lT) { if (lx<2*lT-2) x = FpX_rem_Montgomery(x,D.mg,T,p); else x = FpX_rem(x,T,p); } y = gen_pow(x, n, (void*)&D, &_sqr_montgomery, &_mul_montgomery); } else { if (lx>=lT) x = FpX_rem(x,T,p); y = gen_pow(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) { GEN V=cgetg(l+2,t_VEC); long i; gel(V,1) = pol_1(varn(T)); if (l==0) return V; gel(V,2) = ZX_copy(x); if (l==1) return V; if (lgefint(p) == 3) { long pp = p[2]; return FlxC_to_ZXC(Flxq_powers(ZX_to_Flx(x, pp), l, ZX_to_Flx(T,pp), pp)); } if (lg(T)>FpX_POW_MONTGOMERY_LIMIT) { GEN mg = FpX_invMontgomery(T,p); gel(V,3) = FpXQ_sqr_mg(x,mg,T,p); if ((degpol(x)<<1) < degpol(T)) { for(i = 4; i < l+2; i++) gel(V,i) = FpXQ_mul_mg(gel(V,i-1),x,mg,T,p); } else { /* use squarings if degree(x) is large */ for(i = 4; i < l+2; i++) gel(V,i) = odd(i)? FpXQ_sqr_mg(gel(V, (i+1)>>1),mg,T,p) : FpXQ_mul_mg(gel(V, i-1),x,mg,T,p); } } else { gel(V,3) = FpXQ_sqr(x,T,p); if ((degpol(x)<<1) < degpol(T)) { for(i = 4; i < l+2; i++) gel(V,i) = FpXQ_mul(gel(V,i-1),x,T,p); } else { /* use squarings if degree(x) is large */ for(i = 4; i < l+2; i++) gel(V,i) = odd(i)? FpXQ_sqr(gel(V, (i+1)>>1),T,p) : FpXQ_mul(gel(V, i-1),x,T,p); } } return V; } /* assume T irreducible mod p */ int FpXQ_issquare(GEN x, GEN T, GEN p) { pari_sp av; GEN m, z; long res; if (lg(x) == 2 || equalui(2, p)) return 1; av = avma; m = diviiexact(subis(powiu(p, degpol(T)), 1), subis(p,1)); z = constant_term( FpXQ_pow(x, m, T, p) ); res = kronecker(z, p) == 1; avma = av; return res; } 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); } static GEN famat_Z_gcd(GEN M, GEN n) { pari_sp av=avma; long i, j, l=lg(M[1]); 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, degpol(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 (q) n_q = mulii(q, n_q); return gerepileuptoint(av, n_q); } static GEN _FpXQ_pow(void *data, GEN x, GEN y) { FpX_muldata *D = (FpX_muldata*)data; return FpXQ_pow(x,y, D->T, D->p); } static ulong _FpXQ_hash(GEN x) { ulong h=0; long i, l=lg(x); for (i=2; iT),varn(D->T),D->p); } while (!signe(z)); return z; } static const struct bb_group FpXQ_star={_FpXQ_mul,_FpXQ_pow,_FpXQ_rand,_FpXQ_hash,cmp_RgX,gequal1}; GEN FpXQ_order(GEN a, GEN ord, GEN T, GEN p) { if (lgefint(p)==3) { pari_sp av=avma; ulong pp=p[2]; GEN z = Flxq_order(ZX_to_Flx(a,pp),ord,ZX_to_Flx(T,pp),pp); return gerepileuptoint(av,z); } else { FpX_muldata s; s.T=T; s.p=p; return gen_eltorder(a,ord, (void*)&s,&FpXQ_star); } } static GEN _FpXQ_easylog(void *E, GEN a, GEN g, GEN ord) { FpX_muldata *s=(FpX_muldata*) E; if (degpol(a)) return NULL; return Fp_FpXQ_log(constant_term(a),g,ord,s->T,s->p); } GEN FpXQ_log(GEN a, GEN g, GEN ord, GEN T, GEN p) { if (lgefint(p)==3) { pari_sp av=avma; ulong pp=p[2]; GEN z = Flxq_log(ZX_to_Flx(a,pp),ZX_to_Flx(g,pp),ord,ZX_to_Flx(T,pp),pp); return gerepileuptoint(av,z); } else { FpX_muldata s; s.T=T; s.p=p; return gen_PH_log(a,g,ord, (void*)&s,&FpXQ_star,_FpXQ_easylog); } } GEN FpXQ_sqrtn(GEN a, GEN n, GEN T, GEN p, GEN *zeta) { if (!signe(a)) { long v=varn(T); if (zeta) *zeta=pol_1(v); return pol_0(v); } if (lgefint(p)==3) { pari_sp av=avma; ulong pp=p[2]; GEN z = Flxq_sqrtn(ZX_to_Flx(a,pp),n,ZX_to_Flx(T,pp),pp,zeta); if (!z) return NULL; z = Flx_to_ZX(z); if (zeta) { *zeta=Flx_to_ZX(*zeta); gerepileall(av,2,&z,zeta); return z; } else return gerepileupto(av, z); } else { FpX_muldata s; s.T=T; s.p=p; return gen_Shanks_sqrtn(a,n,addis(powiu(p,degpol(T)),-1),zeta, (void*)&s,&FpXQ_star); } } GEN FpXQ_norm(GEN x, GEN T, GEN p) { pari_sp av = avma; 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 T, GEN p) { pari_sp av = avma; GEN z = FpX_mul(x, FpX_deriv(T, p), p); z = FpX_div(RgX_shift_shallow(z, 1), T, p); return gerepileuptoint(av, constant_term(z)); } GEN FpXQ_charpoly(GEN x, GEN T, GEN p) { pari_sp ltop=avma; long v=varn(T); GEN R; T = leafcopy(T); setvarn(T, MAXVARN); x = leafcopy(x); setvarn(x, MAXVARN); R = FpX_FpXY_resultant(T, deg1pol_shallow(gen_1,FpX_neg(x,p),v),p); return gerepileupto(ltop,R); } GEN FpXQ_minpoly(GEN x, GEN T, GEN p) { pari_sp ltop=avma; GEN G,R=FpXQ_charpoly(x, T, p); GEN dR=FpX_deriv(R,p); while (signe(dR)==0) { R = RgX_deflate(R,itos(p)); dR = FpX_deriv(R,p); } G=FpX_gcd(R,dR,p); G=FpX_normalize(G,p); G=FpX_div(R,G,p); return gerepileupto(ltop,G); } GEN FpXQ_conjvec(GEN x, GEN T, GEN p) { pari_sp av=avma; long i; long n = degpol(T), v = varn(T); GEN M = FpXQ_matrix_pow(FpXQ_pow(pol_x(v),p,T,p),n,n,T,p); GEN z = cgetg(n+1,t_COL); gel(z,1) = RgX_to_RgV(x,n); for (i=2; i<=n; i++) gel(z,i) = FpM_FpC_mul(M,gel(z,i-1),p); gel(z,1) = x; for (i=2; i<=n; i++) gel(z,i) = RgV_to_RgX(gel(z,i),v); return gerepilecopy(av,z); } GEN gener_FpXQ(GEN T, GEN p, GEN *po) { long i, j, vT = varn(T), f = degpol(T); GEN g, L, L2, p_1, q, o; pari_sp av0 = avma, av; if (f == 1) { GEN L, fa; o = subis(p, 1); fa = Z_factor(o); L = gel(fa,1); L = vecslice(L, 2, lg(L)-1); /* remove 2 for efficiency */ g = cgetg(3, t_POL); g[1] = evalsigne(1) | evalvarn(vT); gel(g,2) = pgener_Fp_local(p, L); if (po) *po = mkvec2(o, fa); return g; } if (lgefint(p) == 3) { ulong pp = (ulong)p[2]; g = gener_Flxq(ZX_to_Flx(T, pp), pp, po); g = Flx_to_ZX(g); if (!po) g = gerepileupto(av0, g); else { gel(*po,2) = Flx_to_ZX(gel(*po,2)); gerepileall(av0, 2, &g, po); } return g; } p_1 = subis(p,1); q = diviiexact(subis(powiu(p,f), 1), p_1); L = NULL; (void)Z_lvalrem(p_1, 2, &L); L = gel(Z_factor(L),1); for (i=lg(L)-1; i; i--) gel(L,i) = diviiexact(p_1, gel(L,i)); o = factor_pn_1(p,f); L2 = leafcopy( gel(o, 1) ); for (i = j = 1; i < lg(L2); i++) { if (remii(p_1, gel(L2,i)) == gen_0) continue; gel(L2,j++) = diviiexact(q, gel(L2,i)); } setlg(L2, j); for (av = avma;; avma = av) { GEN t; g = random_FpX(f, vT, p); if (degpol(g) < 1) continue; t = FpX_resultant(T, g, p); /* Ng = g^q, assuming T is monic */ if (equali1(t) || !is_gener_Fp(t, p, p_1, L)) continue; t = FpXQ_pow(g, shifti(p_1,-1), T, p); for (i = 1; i < j; i++) { GEN a = FpXQ_pow(t, gel(L2,i), T, p); if (!degpol(a) && equalii(gel(a,2), p_1)) break; } if (i == j) break; } if (!po) g = gerepilecopy(av0, g); else { *po = mkvec2(subis(powiu(p,f), 1), o); gerepileall(av0, 2, &g, po); } return g; } pari-2.5.5/src/basemath/arith2.c0000644000175000017500000007064612147140046015030 0ustar billbill/* $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. */ /*********************************************************************/ /** **/ /** ARITHMETIC FUNCTIONS **/ /** (second part) **/ /** **/ /*********************************************************************/ #include "pari.h" #include "paripriv.h" /* 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. */ static byteptr initprimes1(ulong size, long *lenp, long *lastp) { long k; byteptr q, r, s, p = (byteptr)pari_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 = p; *r++ = 2; *r++ = 1; /* 2 and 3 */ for (s=q=r-1; ; s=q) { do q++; while (*q); if (q > fin) break; *r++ = (unsigned char) ((q-s) << 1); } *r++ = 0; *lenp = r - p; *lastp = ((s - p) << 1) + 1; return (byteptr) pari_realloc(p,r-p); } /* 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 (not applicable anymore) * 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 treathing 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, long model_type) { 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 diffenent choices of max() happens whe 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. It turns out that the minimization problem is not very nasty. (As usual with minimization problems which depend on parameters, different values of A,B lead to different algorithms. However, the boundaries between the domains in (A,B) plane where different algorithms work are explicitly calculatable.) Thus 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. */ if (model_type != 0) pari_err(talker, "unsupported type of cache model"); /* Future expansion */ /* 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(talker, "panic: 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; } static void sieve_chunk(byteptr known_primes, ulong s, byteptr data, ulong count) { /* start must be odd; prime differences (starting from (5-3)=2) start at known_primes[2], are terminated by a 0 byte; Checks cnt odd numbers starting at 'start', setting bytes starting at data to 0 or 1 depending on whether the corresponding odd number is prime or not */ ulong p; byteptr q; register byteptr write_to = data; /* Better code with gcc 2.8.1 */ register ulong cnt = count; /* Better code with gcc 2.8.1 */ register ulong start = s; /* Better code with gcc 2.8.1 */ register ulong delta = 1; /* Better code with gcc 2.8.1 */ memset(data, 0, cnt); start >>= 1; /* (start - 1)/2 */ start += cnt; /* Corresponds to the end */ cnt -= 1; /* data corresponds to start. q runs over primediffs. */ /* Don't care about DIFFPTR_SKIP: false positives provide no problem */ for (q = known_primes + 1, p = 3; delta; delta = *++q, p += delta) { /* first odd number which is >= start > p and divisible by p = last odd number which is <= start + 2p - 1 and 0 (mod p) = p + the last even number which is <= start + p - 1 and 0 (mod p) = p + the last even number which is <= start + p - 2 and 0 (mod p) = 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) { write_to[off] = 1; off -= p; } } } /* Here's the workhorse. This is recursive, although normally the first recursive call will bottom out and invoke initprimes1() at once. (Not static; might conceivably be useful to someone in library mode) */ byteptr initprimes0(ulong maxnum, long *lenp, ulong *lastp) { long size, alloced, psize; byteptr q, fin, p, p1, fin1, plast, curdiff; ulong last, remains, curlow, rootnum, asize; ulong prime_above = 3; byteptr p_prime_above; if (maxnum <= 1ul<<17) /* Arbitrary. */ return initprimes1(maxnum>>1, lenp, (long*)lastp); /* Break recursion */ maxnum |= 1; /* make it odd. */ /* Checked to be enough up to 40e6, attained at 155893 */ /* Due to multibyte representation of large gaps, this estimate will be broken by large enough maxnum. However, assuming exponential distribution of gaps with the average log(n), we are safe up to circa exp(-256/log(1/0.09)) = 1.5e46. OK with LONG_BITS <= 128. ;-) */ size = (long) (1.09 * maxnum/log((double)maxnum)) + 146; p1 = (byteptr) pari_malloc(size); rootnum = (ulong) sqrt((double)maxnum); /* cast it back to a long */ rootnum |= 1; { byteptr p2 = initprimes0(rootnum, &psize, &last); /* recursive call */ memcpy(p1, p2, psize); pari_free(p2); } fin1 = p1 + psize - 1; remains = (maxnum - rootnum) >> 1; /* number of odd numbers to check */ /* Actually, we access primes array of psize too; but we access it consequently, thus we do not include it in fixed_to_cache */ asize = good_arena_size((ulong)(rootnum * slow2_in_roots), remains + 1, 0, &cache_model, 0) - 1; /* enough room on the stack ? */ alloced = (((byteptr)avma) <= ((byteptr)bot) + asize); if (alloced) p = (byteptr) pari_malloc(asize + 1); else p = (byteptr) bot; fin = p + asize; /* the 0 sentinel goes at fin. */ curlow = rootnum + 2; /* First candidate: know primes up to rootnum (odd). */ curdiff = fin1; /* During each iteration p..fin-1 represents a range of odd numbers. plast is a pointer which represents the last prime seen, it may point before p..fin-1. */ plast = p - ((rootnum - last) >> 1) - 1; p_prime_above = p1 + 2; while (remains) /* Cycle over arenas. Performance is not crucial */ { unsigned char was_delta; if (asize > remains) { asize = remains; fin = 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; /* Put a 0 sentinel for sieve_chunk */ sieve_chunk(p1, curlow, p, asize); *p_prime_above = was_delta; /* Restore */ p[asize] = 0; /* Put a 0 sentinel for ZZZ */ /* now q runs over addresses corresponding to primes */ for (q = p; ; plast = q++) { long d; while (*q) q++; /* use ZZZ 0-sentinel at end */ if (q >= fin) break; d = (q - plast) << 1; while (d >= DIFFPTR_SKIP) *curdiff++ = DIFFPTR_SKIP, d -= DIFFPTR_SKIP; *curdiff++ = (unsigned char)d; } plast -= asize; remains -= asize; curlow += (asize<<1); } /* while (remains) */ last = curlow - ((p - plast) << 1); *curdiff++ = 0; /* sentinel */ *lenp = curdiff - p1; *lastp = last; if (alloced) pari_free(p); return (byteptr) pari_realloc(p1, *lenp); } #if 0 /* not yet... GN */ /* The diffptr table will contain at least 6548 entries (up to and including the 6547th prime, 65557, and the terminal null byte), because the isprime/ small-factor-extraction machinery wants to depend on everything up to 65539 being in the table, and we might as well go to a multiple of 4 Bytes.--GN */ void init_tinyprimes_tridiv(byteptr p); /* in ifactor2.c */ #endif static ulong _maxprime = 0; ulong maxprime(void) { return _maxprime; } void maxprime_check(ulong c) { if (_maxprime < c) pari_err(primer1, c); } /* assume ptr is the address of a diffptr containing the succesive * differences between primes, and p = current prime (up to *ptr excluded) * return smallest prime >= a, update ptr */ ulong init_primepointer(ulong a, ulong p, byteptr *ptr) { byteptr diff = *ptr; if (a <= 0) a = 2; maxprime_check((ulong)a); while (a > p) NEXT_PRIME_VIADIFF(p,diff); *ptr = diff; return p; } byteptr initprimes(ulong maxnum) { long len; ulong last; byteptr p; /* The algorithm must see the next prime beyond maxnum, whence the +512. */ ulong maxnum1 = ((maxnum<65302?65302:maxnum)+512ul); if ((maxnum>>1) > LONG_MAX - 1024) pari_err(talker, "Too large primelimit"); p = initprimes0(maxnum1, &len, &last); #if 0 /* not yet... GN */ static int build_the_tables = 1; if (build_the_tables) { init_tinyprimes_tridiv(p); build_the_tables=0; } #endif _maxprime = last; 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(arither1); 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] where * p, e are vecsmall with n = prod{p[i]^e[i]} */ GEN factoru(ulong n) { GEN f = cgetg(3,t_VEC); pari_sp av = avma; GEN F, P, E, p, e; long i, l; /* enough room to store <= 15 primes and exponents (OK if n < 2^64) */ (void)new_chunk((15 + 1)*2); F = Z_factor(utoi(n)); P = gel(F,1); E = gel(F,2); l = lg(P); avma = av; p = cgetg(l,t_VECSMALL); gel(f,1) = p; e = cgetg(l,t_VECSMALL); gel(f,2) = e; for (i = 1; i < l; i++) { p[i] = itou(gel(P,i)); e[i] = itou(gel(E,i)); } return f; } /* 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 = Z_factor(utoi(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] = itou(gel(P,i)); e[i] = itou(gel(E,i)); c[i] = upowuu(p[i], e[i]); } return f; } /* factor p^n - 1, assuming p prime */ GEN factor_pn_1(GEN p, long n) { pari_sp av = avma; GEN A = Z_factor(subis(p,1)), 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): trivfact(); 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 /***********************************************************************/ /** **/ /** MISCELLANEOUS ARITHMETIC FUNCTIONS **/ /** (ultimately depend on Z_factor()) **/ /** **/ /***********************************************************************/ GEN divisors(GEN n) { pari_sp av = avma; long i, j, l, tn = typ(n); ulong nbdiv; int isint = 1; GEN *d, *t, *t1, *t2, *t3, P, E, e; if (tn == t_MAT && lg(n) == 3) { P = gel(n,1); l = lg(P); for (i = 1; i < l; i++) if (typ(gel(P,i)) != t_INT) { isint = 0; break; } } else { if (tn == t_INT) n = Z_factor(n); else { if (is_matvec_t(tn)) pari_err(typeer,"divisors"); isint = 0; n = factor(n); } P = gel(n,1); l = lg(P); } E = gel(n,2); if (isint && l>1 && signe(P[1]) < 0) { E++; P++; l--; } /* skip -1 */ e = cgetg(l, t_VECSMALL); nbdiv = 1; 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(typeer,"corepartial"); 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(typeer,"core2partial"); return gerepilecopy(av, core2fa(Z_factor_limit(n,all))); } GEN core(GEN n) { pari_sp av = avma; if (typ(n) != t_INT) pari_err(typeer,"core"); return gerepileuptoint(av, corefa(Z_factor(n))); } GEN core2(GEN n) { pari_sp av = avma; if (typ(n) != t_INT) pari_err(typeer,"core"); return gerepilecopy(av, core2fa(Z_factor(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(n); GEN c = gel(y,1), f = gel(y,2); if (_mod4(c)<=1) return 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); } pari-2.5.5/src/basemath/trans2.c0000644000175000017500000012355112147140046015042 0ustar billbill/* $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. */ /********************************************************************/ /** **/ /** TRANSCENDENTAL FUNCTIONS **/ /** (part 2) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" GEN trans_fix_arg(long *prec, GEN *s0, GEN *sig, 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 < 3) l = 3; *res = cgetc(l); *av = avma; if (typ(s) == t_COMPLEX) { /* s = sig + i t */ s = cxtofp(s, l+1); *sig = gel(s,1); } else /* real number */ { *sig = s = gtofp(s, l+1); 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 = lg(x); if (absrnz_equal1(x)) { /* |x| = 1 */ y = Pi2n(-2, l+1); 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 += divsBIL(e); y = cgetr(lp); av0 = avma; p1 = rtor(x, l+1); 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)(bit_accuracy(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 + nbits2nlong(m); p2 = rtor(p1, l2); av = avma; for (i=1; i<=m; i++) { p5 = addsr(1, sqrr(p2)); setlg(p5,l2); p5 = addsr(1, sqrtr_abs(p5)); setlg(p5,l2); affrr(divrr(p2,p5), p2); avma = av; } p3 = sqrr(p2); l1 = minss(4, l2); /* l1 increases to l2 */ unr = real_1(l2); setlg(unr, l1); p4 = cgetr(l2); setlg(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 */ { setlg(p3,l1); p5 = mulrr(p4,p3); l1 += dvmdsBIL(s - e, &s); if (l1 > l2) l1 = l2; setlg(unr,l1); p5 = subrr(divru(unr,2*i-1), p5); setlg(p4,l1); affrr(p5,p4); avma = av; } setlg(p3, l2); p5 = mulrr(p4,p3); /* i = 1 */ setlg(unr,l2); p4 = subrr(unr, p5); p4 = mulrr(p2,p4); setexpo(p4, expo(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(gath(mulcxI(x),prec))); case t_INTMOD: case t_PADIC: pari_err(typeer,"gatan"); default: av = avma; if (!(y = toser_i(x))) break; if (valp(y) < 0) pari_err(negexper,"gatan"); if (lg(y)==2) return gerepilecopy(av, y); /* lg(y) > 2 */ a = integ(gdiv(derivser(y), gaddsg(1,gsqr(y))), varn(y)); if (!valp(y)) a = gadd(a, gatan(gel(y,2),prec)); return gerepileupto(av, a); } return transc(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 (lg(x) > AGM_ATAN_LIMIT) { z = logagmcx(mkcomplex(a,x), lg(x)); z = gel(z,2); } else z = mpatan(divrr(x, a)); return gerepileuptoleaf(av, z); } static GEN mpach(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, lg(x)); /* 1 */ y = Pi2n(-1, lg(x)); setsigne(y, -1); return y; /* -1 */ } if (expo(x) < 0) return mpasin(x); y = cgetg(3,t_COMPLEX); gel(y,1) = Pi2n(-1, lg(x)); gel(y,2) = mpach(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(gash(mulcxI(x), prec))); case t_INTMOD: case t_PADIC: pari_err(typeer,"gasin"); 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(negexper,"gasin"); 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 = integ(p1,varn(y)); if (!valp(y)) a = gadd(a, gasin(gel(y,2),prec)); return gerepileupto(av, a); } return transc(gasin,x,prec); } /********************************************************************/ /** **/ /** ARCCOSINE **/ /** **/ /********************************************************************/ static GEN acos0(long e) { long l = divsBIL(e); if (l >= 0) l = -1; return Pi2n(-1, 2-l); } /* |x| < 1, x != 0 */ static GEN mpacos(GEN x) { pari_sp av = avma; GEN z, a = sqrtr(subsr(1, sqrr(x))); if (lg(x) > AGM_ATAN_LIMIT) { z = logagmcx(mkcomplex(x,a), lg(x)); z = gel(z,2); } else { z = mpatan(divrr(a, x)); if (signe(x) < 0) z = addrr(mppi(lg(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_accuracy(lg(x))>>1) ) : mppi(lg(x)); if (expo(x) < 0) return mpacos(x); y = cgetg(3,t_COMPLEX); p1 = mpach(x); if (sx < 0) { gel(y,1) = mppi(lg(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)); case t_INTMOD: case t_PADIC: pari_err(typeer,"gacos"); case t_SER: av = avma; if (!(y = toser_i(x))) break; if (valp(y) < 0) pari_err(negexper,"gacos"); if (lg(y) > 2) { p1 = gsubsg(1,gsqr(y)); if (gequal0(p1)) return zeroser(varn(y), valp(p1)>>1); p1 = integ(gdiv(gneg(derivser(y)), gsqrt(p1,prec)), varn(y)); if (gequal1(gel(y,2)) && !valp(y)) /*y(t) = 1+O(t)*/ 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 transc(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(lg(x)); } prec = lg(y); if (prec < lg(x)) prec = lg(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 rdivii(gel(x,1),gel(x,2), prec); case t_REAL: break; default: pari_err(typeer,"rfix (conversion to t_REAL)"); } 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) { long tx = typ(x); pari_sp av; if (gequal0(x)) pari_err(talker,"zero argument in garg"); switch(tx) { case t_REAL: prec = lg(x); /* fall through */ case t_INT: case t_FRAC: return (gsigne(x)>0)? real_0(prec): mppi(prec); case t_QUAD: av = avma; return gerepileuptoleaf(av, garg(quadtofp(x, prec), prec)); case t_COMPLEX: return cxarg(gel(x,1),gel(x,2),prec); case t_VEC: case t_COL: case t_MAT: return transc(garg,x,prec); } pari_err(typeer,"garg"); return NULL; /* not reached */ } /********************************************************************/ /** **/ /** HYPERBOLIC COSINE **/ /** **/ /********************************************************************/ static GEN mpch(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)); setexpo(z, expo(z)-1); return gerepileuptoleaf(av, z); } GEN gch(GEN x, long prec) { pari_sp av; GEN y, p1; switch(typ(x)) { case t_REAL: return mpch(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)); case t_INTMOD: pari_err(typeer,"gch"); 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 transc(gch,x,prec); } /********************************************************************/ /** **/ /** HYPERBOLIC SINE **/ /** **/ /********************************************************************/ static GEN mpsh(GEN x) { pari_sp av; long ex = expo(x), lx; GEN z, res; if (!signe(x)) return real_0_bit(ex); lx = lg(x); res = cgetr(lx); av = avma; if (ex < 1 - BITS_IN_LONG) x = rtor(x, lx + nbits2nlong(-ex)-1); z = mpexp(x); z = subrr(z, invr(z)); setexpo(z, expo(z)-1); affrr(z, res); avma = av; return res; } GEN gsh(GEN x, long prec) { pari_sp av; GEN y, p1; switch(typ(x)) { case t_REAL: return mpsh(x); case t_COMPLEX: if (isintzero(gel(x,1))) { GEN z = cgetg(3, t_COMPLEX); gel(z,1) = gen_0; gel(z,2) = gsin(gel(x,2),prec); return z; } /* fall through */ case t_PADIC: av = avma; p1 = gexp(x,prec); p1 = gsub(p1, ginv(p1)); return gerepileupto(av, gmul2n(p1,-1)); case t_INTMOD: 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 transc(gsh,x,prec); } /********************************************************************/ /** **/ /** HYPERBOLIC TANGENT **/ /** **/ /********************************************************************/ static GEN mpth(GEN x) { long lx, s = signe(x); GEN y; if (!s) return real_0_bit(expo(x)); lx = lg(x); if (absr_cmp(x, stor(bit_accuracy(lx), 3)) >= 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 + nbits2nlong(-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 gth(GEN x, long prec) { pari_sp av; GEN y, t; switch(typ(x)) { case t_REAL: return mpth(x); case t_COMPLEX: if (isintzero(gel(x,1))) { GEN z = cgetg(3, t_COMPLEX); gel(z,1) = gen_0; gel(z,2) = gtan(gel(x,2),prec); return z; } /* 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)); case t_INTMOD: pari_err(typeer,"gth"); 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 transc(gth,x,prec); } /********************************************************************/ /** **/ /** AREA HYPERBOLIC SINE **/ /** **/ /********************************************************************/ /* x != 0 */ static GEN mpash(GEN x) { GEN z, res; pari_sp av; long lx = lg(x), ex = expo(x); res = cgetr(lx); av = avma; if (ex < 1 - BITS_IN_LONG) x = rtor(x, lx + nbits2nlong(-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 gash(GEN x, long prec) { pari_sp av; GEN a, y, p1; switch(typ(x)) { case t_REAL: if (!signe(x)) return rcopy(x); return mpash(x); case t_COMPLEX: if (ismpzero(gel(x,2))) return gash(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); case t_INTMOD: case t_PADIC: pari_err(typeer,"gash"); default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepilecopy(av, y); if (valp(y) < 0) pari_err(negexper,"gash"); 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 = integ(p1,varn(y)); if (!valp(y)) a = gadd(a, gash(gel(y,2),prec)); return gerepileupto(av, a); } return transc(gash,x,prec); } /********************************************************************/ /** **/ /** AREA HYPERBOLIC COSINE **/ /** **/ /********************************************************************/ /* |x| >= 1, return ach(|x|) */ static GEN mpach(GEN x) { pari_sp av = avma; GEN z; if (absrnz_equal1(x)) return real_0_bit(- (bit_accuracy(lg(x)) >> 1)); z = logr_abs( addrr_sign(x, 1, sqrtr( subrs(sqrr(x), 1) ), 1) ); return gerepileuptoleaf(av, z); } GEN gach(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 mpach(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 = mpach(x); b = mppi(lg(x)); } gel(y,1) = a; gel(y,2) = b; return y; } case t_COMPLEX: if (ismpzero(gel(x,2))) return gach(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); case t_INTMOD: case t_PADIC: pari_err(typeer,"gach"); default: { GEN a; long v; av = avma; if (!(y = toser_i(x))) break; v = valp(y); if (v < 0) pari_err(negexper,"gach"); 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 = integ(p1, varn(y)); if (v) p1 = PiI2n(-1, prec); /* I Pi/2 */ else { p1 = gel(y,2); if (gequal1(p1)) return gerepileupto(av,a); p1 = gach(p1, prec); } return gerepileupto(av, gadd(p1,a)); } } return transc(gach,x,prec); } /********************************************************************/ /** **/ /** AREA HYPERBOLIC TANGENT **/ /** **/ /********************************************************************/ /* |x| < 1, x != 0 */ static GEN mpath(GEN x) { pari_sp av = avma; long ex = expo(x); GEN z; if (ex < 1 - BITS_IN_LONG) x = rtor(x, lg(x) + nbits2nlong(-ex)-1); z = invr( subsr(1,x) ); setexpo(z, expo(z)+1); /* 2/(1-x)*/ z = logr_abs( addrs(z,-1) ); setexpo(z, expo(z)-1); return gerepileuptoleaf(av, z); } GEN gath(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 mpath(x); y = cgetg(3,t_COMPLEX); av = avma; z = subrs(x,1); if (!signe(z)) pari_err(talker,"singular argument in atanh"); z = invr(z); setexpo(z, expo(z)+1); /* 2/(x-1)*/ z = addrs(z,1); if (!signe(z)) pari_err(talker,"singular argument in atanh"); z = logr_abs(z); setexpo(z, expo(z)-1); /* (1/2)log((1+x)/(x-1)) */ gel(y,1) = gerepileuptoleaf(av, z); gel(y,2) = Pi2n(-1, lg(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 gath(gel(x,1), prec); av = avma; z = glog( gaddgs(gdivsg(2,gsubsg(1,x)),-1), prec ); return gerepileupto(av, gmul2n(z,-1)); case t_INTMOD: case t_PADIC: pari_err(typeer,"gath"); default: av = avma; if (!(y = toser_i(x))) break; if (valp(y) < 0) pari_err(negexper,"gath"); z = gdiv(derivser(y), gsubsg(1,gsqr(y))); a = integ(z, varn(y)); if (!valp(y)) a = gadd(a, gath(gel(y,2),prec)); return gerepileupto(av, a); } return transc(gath,x,prec); } /********************************************************************/ /** **/ /** CACHE BERNOULLI NUMBERS B_2k **/ /** **/ /********************************************************************/ /* is B_{2k} precomputed at precision >= prec ? */ int OK_bern(long k, long prec) { return (bernzone && bernzone[1] >= k && bernzone[2] >= prec); } #define BERN(i) (B + 3 + (i)*B[2]) #define set_bern(c0, i, B) STMT_START { \ *(BERN(i)) = c0; affrr(B, BERN(i)); } STMT_END /* compute B_0,B_2,...,B_2*nb */ void mpbern(long nb, long prec) { long i, l, c0; pari_sp av; GEN B; pari_timer T; prec++; /* compute one more word of accuracy than required */ if (OK_bern(nb, prec)) return; if (nb < 0) nb = 0; l = 3 + prec*(nb+1); B = newblock(l); B[0] = evaltyp(t_STR) | evallg(l); /* dummy non-recursive type */ B[1] = nb; B[2] = prec; av = avma; c0 = evaltyp(t_REAL) | evallg(prec); *(BERN(0)) = c0; affsr(1, BERN(0)); if (bernzone && bernzone[2] >= prec) { /* don't recompute known Bernoulli */ for (i = 1; i <= bernzone[1]; i++) set_bern(c0, i, bern(i)); } else i = 1; if (DEBUGLEVEL) { err_printf("caching Bernoulli numbers 2*%ld to 2*%ld, prec = %ld\n", i,nb,prec); timer_start(&T); } if (i == 1 && nb > 0) { set_bern(c0, 1, divru(real_1(prec), 6)); /* B2 = 1/6 */ i = 2; } /* B_{2i} = (2i-1) / (4i+2) - * sum_{a = 1}^{i-1} (2i)...(2i+2-2a) / (2...(2a-1)2a) B_{2a} */ for ( ; i <= nb; i++, avma = av) { /* i > 1 */ #ifdef LONG_IS_64BIT const ulong mul_overflow = 3037000500; #else const ulong mul_overflow = 46341; #endif ulong u = 8, v = 5, a = i-1, b = 2*i-3; GEN S = BERN(a); for (;;) { /* b = 2a-1, u = 2v-2, 2a + v = 2i+3 */ if (a == 1) { S = mulri(S, muluu(u,v)); break; } /* a=b=1, v=2i+1, u=4i */ /* 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(a), S); if ((a & 127) == 0) { set_bern(c0, i, S); S = BERN(i); avma = av; } } S = divru(subsr(2*i, S), 2*i+1); setexpo(S, expo(S) - 2*i); set_bern(c0, i, S); /* S = B_2i */ } if (DEBUGLEVEL) timer_printf(&T, "Bernoulli"); if (bernzone) killblock(bernzone); avma = av; bernzone = B; } #undef BERN GEN bernreal(long n, long prec) { GEN B; if (n==1) { B = stor(-1, prec); setexpo(B,-1); return B; } if (n<0 || n&1) return gen_0; n >>= 1; mpbern(n+1,prec); B=cgetr(prec); affrr(bern(n),B); return B; } static GEN B2(void){ GEN z = cgetg(3, t_FRAC); gel(z,1) = gen_1; gel(z,2) = utoipos(6); return z; } static GEN B4(void) { GEN z = cgetg(3, t_FRAC); gel(z,1) = gen_m1; gel(z,2) = utoipos(30); return z; } GEN bernfrac(long k) { if (k < 6) switch(k) { case 0: return gen_1; case 1: return mkfrac(gen_m1, gen_2); case 2: return B2(); case 4: return B4(); default: return gen_0; } if (k & 1) return gen_0; return bernfrac_using_zeta(k); } /* 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) { GEN y = cgetg(nb+2, t_VEC), z = y + 1; long i; if (nb < 20) return bernvec_old(nb); for (i = nb; i > 2; i--) gel(z,i) = bernfrac_using_zeta(i << 1); gel(y,3) = B4(); gel(y,2) = B2(); gel(y,1) = gen_1; return y; } /********************************************************************/ /** **/ /** 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; setlg(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, 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,&av,&res); esig = expo(sig); et = (typ(s) == t_REAL) ? 0: gexpo(gel(s,2)); 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,3); /* l2 ~ |lngamma(s))|^2 */ l2 = gnorm(gmul(S, glog(S, 3))); l = (bit_accuracy_mul(prec, LOG2) - rtodbl(glog(l2,3))/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,3); 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 = rtodbl(imag_i(s)); double la, l,l2,u,v, rlogs, ilogs; 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 = (bit_accuracy_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); } prec++; av2 = avma; avlim = stack_lim(av2,3); y = s; if (typ(s0) == t_INT) { if (signe(s0) <= 0) pari_err(talker,"non-positive integer argument in cxgamma"); 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); 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)) { 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); setexpo(z, expo(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); } setexpo(z, expo(z) + v); } affrr(z, y); avma = av; return y; } GEN ggamd(GEN x, long prec) { pari_sp av, tetpil; switch(typ(x)) { case t_INT: { long k = itos(x); if (labs(k) > 962353) pari_err(talker, "argument too large in ggamd"); return gammahs(k<<1, prec); } case t_REAL: case t_FRAC: case t_COMPLEX: case t_QUAD: case t_PADIC: av=avma; x = gadd(x,ghalf); tetpil=avma; return gerepile(av,tetpil,ggamma(x,prec)); case t_INTMOD: pari_err(typeer,"ggamd"); case t_SER: pari_err(impl,"gamd of a power series"); } return transc(ggamd,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; k = itos( gceil(gdiv(mulsi(k, sqrs(p)), sqrs(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; 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 (valp(x) < 0) pari_err(talker,"Gamma not defined for non-integral p-adic number"); 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(talker,"non-positive integer argument in ggamma"); if (cmpiu(x,481177) > 0) pari_err(talker,"argument too large in ggamma"); 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(talker, "argument too large in ggamma"); return NULL; /* not reached */ } return gammahs(m-1, prec); case t_PADIC: return Qp_gamma(x); case t_INTMOD: pari_err(typeer,"ggamma"); default: av = avma; if (!(y = toser_i(x))) break; return gerepileupto(av, gexp(glngamma(y,prec),prec)); } return transc(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) { long i, n; pari_sp av; GEN a, y, p1; switch(typ(x)) { case t_INT: if (signe(x) <= 0) pari_err(talker,"non-positive integer in glngamma"); 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_REAL: case t_COMPLEX: return cxgamma(x, 1, prec); default: av = avma; if (!(y = toser_i(x))) break; if (valp(y)) pari_err(negexper,"glngamma"); p1 = gsubsg(1,y); if (!valp(p1)) pari_err(impl,"lngamma around a!=1"); n = (lg(y)-3) / valp(p1); a = zeroser(varn(y), lg(y)-2); for (i=n; i>=2; i--) a = gmul(p1, gadd(a, gdivgs(szeta(i, prec),i))); a = gadd(a, mpeuler(prec)); return gerepileupto(av, gmul(a, p1)); case t_PADIC: pari_err(impl,"p-adic lngamma function"); case t_INTMOD: pari_err(typeer,"glngamma"); } return transc(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,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,&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(talker,"non-positive integer argument in cxpsi"); if (expo(sig) > 300 || (typ(s) == t_COMPLEX && gexpo(gel(s,2)) > 300)) { /* |s| is HUGE. Play safe */ GEN L, S = gprec_w(s,3), rS = real_i(S), iS = imag_i(S); double l; l = rtodbl( gnorm(glog(S, 3)) ); l = log(l) / 2.; lim = 2 + (long)ceil((bit_accuracy_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 = 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((bit_accuracy_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); } 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); 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); } GEN gpsi(GEN x, long prec) { switch(typ(x)) { case t_REAL: case t_COMPLEX: return cxpsi(x,prec); case t_INTMOD: case t_PADIC: pari_err(typeer,"gpsi"); case t_SER: pari_err(impl,"psi of power series"); } return transc(gpsi,x,prec); } pari-2.5.5/src/basemath/ZX.c0000644000175000017500000003360012147140046014165 0ustar billbill/* $Id$ 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 */ /* */ /*******************************************************************/ static int _check_ZX(GEN x) { long k = lg(x)-1; for ( ; k>1; k--) if (typ(x[k])!=t_INT) return 0; return 1; } void RgX_check_ZX(GEN x, const char *s) { if (! _check_ZX(x)) pari_err(talker,"polynomial not in Z[X] in %s",s); } void RgX_check_ZXY(GEN x, const char *s) { long k = lg(x)-1; for ( ; k>1; k--) { GEN t = gel(x,k); switch(typ(t)) { case t_INT: break; case t_POL: if (_check_ZX(t)) break; /* fall through */ default: pari_err(talker,"polynomial not in Z[X,Y] in %s",s); } } } long ZXY_max_lg(GEN x) { long i, prec = 0, lx = lg(x); for (i=2; i prec) prec = l; } return prec; } long ZX_max_lg(GEN x) { long i, prec = 0, lx = lg(x); for (i=2; i prec) prec = l; } return prec; } /*Renormalize (in place) polynomial with t_INT or t_POL coefficients.*/ GEN ZX_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; } 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--) { gel(Q,i) = mulii(gel(P,i), hi); if (i == 2) break; hi = mulii(hi,h); } 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); } pari-2.5.5/src/basemath/subgroup.c0000644000175000017500000003770312147140046015502 0ustar billbill/* $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. */ #include "pari.h" #include "paripriv.h" typedef struct slist { struct slist *next; long *data; long prec; } slist; typedef struct { GEN hnfgroup, 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++) for(i=1; i<=j; i++) { long l = lgefint(gcoeff(H,i,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_hnf(shallowconcat(S->hnfgroup,x)); 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(bugparier,"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(typeer,"subgroup"); 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(typeer,"subgroup"); T->boundtype = b_TYPE; break; default: pari_err(typeer,"subgroup"); } if (signe(T->bound) <= 0) pari_err(talker,"subgroup: index bound must be positive"); } 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,nbprim, n = lg(cyc); if (typ(cyc) != t_VEC) { if (typ(cyc) != t_MAT) pari_err(typeer,"forsubgroup"); 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(cyc[1])) pari_err(talker,"infinite group in forsubgroup"); fa = Z_factor(gel(cyc,1)); primlist = gel(fa,1); nbprim = lg(primlist); listL = new_chunk(n); 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 (nbprim == 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(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(typeer,"forsubgroup"); 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.5.5/src/basemath/buch1.c0000644000175000017500000006677212147140046014646 0ustar billbill/* $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. */ #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= B) pari_err(talker,"sorry, couldn't deal with this field. PLEASE REPORT"); if (cbach <= 0.3) cbach *= 2; else cbach += 0.2; if (cbach > B) cbach = B; if (DEBUGLEVEL) err_printf("\n*** Bach constant: %f\n", cbach); return cbach; } /* 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; i> 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; } /* create B->FB, B->numFB; set B->badprim. Return L(kro_D, 1) */ static GEN FBquad(struct buch_quad *B, long C2, long C1, GRHcheck_t *S) { GEN Res = real_1(DEFAULTPREC), D = B->QFR->D; double L = log((double)C2), SA = 0, SB = 0; long i, p, s, LIM; pari_sp av; byteptr d = diffptr; B->numFB = cgetg(C2+1, t_VECSMALL); B->FB = cgetg(C2+1, t_VECSMALL); av = avma; B->KC = 0; i = 0; maxprime_check((ulong)C2); B->badprim = gen_1; for (p = 0;;) /* p <= C2 */ { NEXT_PRIME_VIADIFF(p, d); if (!B->KC && p > C1) B->KC = i; if (p > C2) break; s = krois(D,p); if (s) Res = mulur(p, divru(Res, p - s)); switch (s) { case -1: break; /* inert */ case 0: /* ramified */ if (is_bad(D, (ulong)p)) { B->badprim = muliu(B->badprim, p); break; } /* fall through */ default: /* split */ i++; B->numFB[p] = i; B->FB[i] = p; break; } if (!S->checkok) { double logp = log((double)p); double logNP = s < 0? 2*logp: logp; double q = s < 0? 1/(double)p: 1/sqrt((double)p); double A = logNP * q, B = logNP * A; long M = (long)(L/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 (s > 0) { SA += 2 * A; SB += 2 * B; } else { SA += A; SB += B; } } } if (!B->KC) return NULL; if (!GRHok(S, L, SA, SB)) return NULL; B->KC2 = i; setlg(B->FB, B->KC2+1); LIM = (expi(D) < 16)? 100: 1000; while (p < LIM) { s = krois(D,p); Res = mulur(p, divru(Res, p - s)); NEXT_PRIME_VIADIFF(p, d); } if (B->badprim != gen_1) gerepileall(av, 2, &Res, &B->badprim); else { B->badprim = NULL; Res = gerepileuptoleaf(av, Res); } S->checkok = 1; return Res; } /* create B->vperm, return B->subFB */ static GEN subFBquad(struct buch_quad *B, GEN D, double PROD) { long i, j, minSFB, lgsub = 1, ino = 1, lv = B->KC+1; double prod = 1.; pari_sp av; GEN no; minSFB = (expi(D) > 15)? 3: 2; 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; } } if (j == lv) return NULL; 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 = const_vecsmall(B->KC, 0); 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]]--; } } else { col = gel(mat,++s); for (i=1; isubFB[i]] = -ex[i]; add_fact(B, col, form); } 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; ulong LIMC, LIMC2, cp; GEN W, cyc, res, gen, dep, mat, C, extraC, B, R, resc, Res, z, h = NULL; /*-Wall*/ double drc, lim, LOGD, LOGD2; GRHcheck_t G, *GRHcheck = &G; 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+1, MEDDEFAULTPREC + 2*(expi(QFR.D)/BITS_IN_LONG)); } 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(talker,"Bach constant <= 0 in Buchquad"); av = avma; BQ.powsubFB = BQ.subFB = NULL; init_GRHcheck(GRHcheck, 2, BQ.PRECREG? 2: 0, LOGD); /* LIMC = Max(cbach*(log D)^2, exp(sqrt(log D loglog D) / 8)) */ START: do { if (!FIRST) cbach = check_bach(cbach,6.); FIRST = 0; avma = av; if (BQ.subFB) gunclone(BQ.subFB); if (BQ.powsubFB) gunclone(BQ.powsubFB); clearhash(BQ.hashtab); LIMC = (ulong)(cbach*LOGD2); if (LIMC < cp) { LIMC = cp; cbach = (double)LIMC / LOGD2; } LIMC2 = (ulong)(maxdd(cbach,cbach2)*LOGD2); if (LIMC2 < LIMC) LIMC2 = LIMC; if (BQ.PRECREG) qfr_data_init(QFR.D, BQ.PRECREG, &QFR); Res = FBquad(&BQ, LIMC2, LIMC, GRHcheck); if (DEBUGLEVEL) timer_printf(&T, "factor base"); } while (!Res || !(BQ.subFB = subFBquad(&BQ, QFR.D, lim + 0.5))); if (DEBUGLEVEL) timer_printf(&T, "subFBquad = %Ps", vecpermute(BQ.FB, BQ.subFB)); nsubFB = lg(BQ.subFB) - 1; 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) = const_vecsmall(BQ.KC, 0); 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) = const_vecsmall(BQ.KC, 0); 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 = lg(dep)>1? lg(dep[1])-1: lg(B[1])-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); z = mulrr(Res, resc); /* ~ hR if enough relations, a multiple otherwise */ switch(get_R(&BQ, C, (lg(C)-1) - (lg(B)-1) - (lg(W)-1), divir(h,z), &R)) { case fupb_PRECI: BQ.PRECREG = (BQ.PRECREG<<1)-2; 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); 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.2, c2 = 0.2; if (!data) lx=1; else { lx = lg(data); if (typ(data)!=t_VEC || lx > 7) pari_err(talker,"incorrect parameters in quadclassunit"); 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.5.5/src/basemath/ellanal.c0000644000175000017500000003314112147140046015234 0ustar billbill/* $Id$ 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. */ /********************************************************************/ /** **/ /** L functions of elliptic curves **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" /* Generic Buhler-Gross algorithm */ struct bg_data { GEN E, N; /* ell, conductor */ GEN bnd; /* t_INT; will need all an for n <= bnd */ ulong rootbnd; /* sqrt(bnd) */ GEN an; /* t_VECSMALL: cache of ap, n <= rootbnd */ GEN ap; /* t_VECSMALL: cache of ap, p <= rootbnd */ GEN p; /* t_VECSMALL: primes <= rootbnd */ long lp; }; typedef void bg_fun(void*el, GEN *psum, GEN n, GEN a, long jmax); static void gen_BG_add(void *E, bg_fun *fun, struct bg_data *bg, GEN *psum, GEN n, long i, GEN a, GEN lasta) { 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); } } static void gen_BG_init(struct bg_data *bg, GEN E, GEN N, GEN bnd, GEN ap) { pari_sp av; long i = 1; bg->E = E; bg->N = N; bg->bnd = bnd; bg->rootbnd = itou(sqrtint(bnd)); bg->lp = uprimepi(bg->rootbnd); bg->p = primes_zv(bg->lp); if (ap) { /* reuse known values */ i = lg(ap); bg->ap = vecsmall_lengthen(ap, maxss(bg->lp,i-1)); } else bg->ap = cgetg(bg->lp+1, t_VECSMALL); av = avma; for ( ; i <= bg->lp; i++, avma = av) bg->ap[i] = itos(ellap(E, utoipos(bg->p[i]))); avma = av; bg->an = const_vecsmall(bg->rootbnd, 0); bg->an[1] = 1; } static GEN gen_BG_rec(void *E, bg_fun *fun, struct bg_data *bg, GEN sum0) { long i, j, lp = bg->lp; GEN bndov2 = shifti(bg->bnd, -1); pari_sp av = avma; GEN sum = gcopy(sum0), p; if(DEBUGLEVEL) err_printf("1st stage, using recursion for p <= %ld\n", bg->p[lp]); 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); sum = gerepileupto(av, sum); } p = nextprime(utoipos(bg->p[lp]+1)); if (DEBUGLEVEL) err_printf("2nd stage, looping for p <= %Ps\n", bndov2); for ( ; cmpii(p, bndov2)<=0; p = nextprime(addis(p,1))) { 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); } gerepileall(av, 2, &sum, &p); } if (DEBUGLEVEL) err_printf("3nd stage, looping for p <= %Ps\n", bg->bnd); for ( ; cmpii(p, bg->bnd)<=0; p = nextprime(addis(p,1))) { GEN a = ellap(bg->E, p); if (!signe(a)) continue; fun(E, &sum, p, a, 0); gerepileall(av, 2, &p, &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. */ struct ellld { GEN E, N; /* ell, conductor */ GEN bnd; /* t_INT; will need all an for n <= bnd */ ulong rootbnd; /* floor(sqrt(bnd)) */ ulong bgbnd; /* rootbnd+1 */ long r; /* we are comuting L^{(r)}(1) */ GEN X; /* t_REAL, 2Pi / sqrt(N) */ GEN eX; /* t_REAL, exp(X) */ GEN emX; /* t_REAL, exp(-X) */ GEN gcache, gjcache, baby, giant; /* t_VEC of t_REALs */ GEN alpha; /* t_VEC of t_REALs, except alpha[1] = gen_1 */ GEN A; /* t_VEC of t_REALs, A[1] = 1 */ long epsbit; }; 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(ceilr(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 = ceilr(divsr(7*bit_accuracy(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)); } static GEN init_Gr(struct ellld *el, long prec) { if (el->r == 0) { el->bgbnd = el->rootbnd+1; el->baby = mpvecpow(el->emX, el->bgbnd); el->giant = mpvecpow(gel(el->baby,el->bgbnd), el->bgbnd); return gel(el->baby, 1); } else 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); } /* m t_INT, returns a t_REAL */ static GEN ellld_G(struct ellld *el, GEN m) { if (cmpiu(m, el->rootbnd) <= 0) return gel(el->gcache, itos(m)); if (el->r == 1) return mpeint1(mulir(m, el->X), powgi(el->eX,m)); return compute_Gr_Sx(el, m, 0); /* r >= 2 */ } /* el->r<=1 */ static GEN ellld_Gmulti(struct ellld *el, GEN p, long jmax) { el->gjcache = mpveceint1(mulir(p,el->X), powgi(el->eX,p), jmax); return gel(el->gjcache, 1); } static void ellld_L1(void *E, GEN *psum, GEN n, GEN a, long j) { struct ellld *el = (struct ellld *) E; GEN G; if (j==0 || el->r>=2) G = ellld_G(el, n); else if (j < 0) G = ellld_Gmulti(el, n, -j); else G = gel(el->gjcache, j); *psum = addrr(*psum, divri(mulir(a, G), n)); } static GEN ellld_L1r0_G(struct ellld *el, GEN n) { GEN q, r; if (cmpiu(n, el->bgbnd) <= 0) return gel(el->baby, itou(n)); q = truedvmdis(n,el->bgbnd,&r); if (signe(r)==0) return gel(el->giant, itou(q)); return gmul(gel(el->baby, itou(r)), gel(el->giant, itou(q))); } static void ellld_L1r0(void *E, GEN *psum, GEN n, GEN a, long j) { struct ellld *el = (struct ellld *) E; GEN G = ellld_L1r0_G(el, n); (void) j; *psum = addrr(*psum, divri(mulir(a, G), n)); } /* 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_Gr(el, prec); if (DEBUGLEVEL>=3) err_printf("el_bnd = %Ps, N=%Ps\n", el->bnd, el->N); sum = gen_BG_rec(el, r?ellld_L1:ellld_L1r0, bg, sum); return mulri(shiftr(sum, 1), mpfact(r)); } static void init_el(struct ellld *el, GEN E, long *parity, long prec) { GEN eX; checksmallell(E); el->E = ell_to_small_red(E, &el->N); el->X = divrr(Pi2n(1, prec), sqrtr(itor(el->N, prec))); /* << 1 */ eX = mpexp(el->X); if (lg(eX) > prec) eX = rtor(eX, prec); /* avoid spurious accuracy increase */ el->eX = eX; el->emX = invr(el->eX); el->epsbit = bit_accuracy(prec)+1; *parity = (ellrootno_global(el->E, el->N) > 0)? 0: 1; /* rank parity */ } GEN ellL1(GEN E, long r, long prec) { pari_sp av = avma; struct ellld el; struct bg_data bg; long parity; if (r<0) pari_err(talker,"derivative order must be nonnegative"); init_el(&el, E, &parity, prec); if (parity != (r & 1)) return gen_0; return gerepileuptoleaf(av, ellL1_i(&el, &bg, r, NULL, 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(-bit_accuracy(prec)/2+1, DEFAULTPREC); else if (typ(eps) != t_REAL) { eps = gtofp(eps, DEFAULTPREC); if (typ(eps) != t_REAL) pari_err(typeer, "ellanalyticrank"); } init_el(&el, e, &rk, prec); /* set rk to rank parity (0 or 1) */ if (DEBUGLEVEL) { err_printf("ellanalyticrank: CURVE = %Ps\n", e); err_printf("Rank is %s\n", rk == 0? "even": "odd"); err_printf("eps = %Ps\nconductor = %Ps\n", eps, el.N); 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); } } pari-2.5.5/src/basemath/buch2.c0000644000175000017500000032070012173305763014637 0ustar billbill/* $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. */ #include "pari.h" #include "paripriv.h" /********************************************************************/ /** **/ /** INSERT PERMANENT OBJECT IN STRUCTURE **/ /** **/ /********************************************************************/ static const long OBJMAX = 2; /* maximum number of insertable objects */ /* insert O in S [last position] */ static void obj_insert(GEN S, GEN O, long K) { long l = lg(S)-1; GEN v = gel(S,l); if (typ(v) != t_VEC) { GEN w = zerovec(OBJMAX); gel(w,K) = O; gel(S,l) = gclone(w); } else gel(v,K) = gclone(O); } static GEN get_extra_obj(GEN S, long K) { GEN v = gel(S,lg(S)-1); if (typ(v) == t_VEC) { GEN O = gel(v,K); if (!isintzero(O)) return O; } return NULL; } GEN check_and_build_obj(GEN S, long tag, GEN (*build)(GEN)) { GEN O = get_extra_obj(S, tag); if (!O) { pari_sp av = avma; obj_insert(S, build(S), tag); avma = av; O = get_extra_obj(S, tag); } return O; } /*******************************************************************/ /* */ /* CLASS GROUP AND REGULATOR (McCURLEY, BUCHMANN) */ /* GENERAL NUMBER FIELDS */ /* */ /*******************************************************************/ static const long RANDOM_BITS = 4; 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[1]; /*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; static void wr_rel(GEN col) { long i, l = lg(col); err_printf("\nrel = "); for (i=1; ilast - cache->base, cache->end - cache->base); wr_rel(cache->last->R); } 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, idealperm = F->idealperm; long i; const long lperm = lg(idealperm); for (sub = F->allsubFB; sub; sub = subold) { GEN subFB = sub->subFB; for (i = 1; i < lg(subFB); i++) { long k, id = subFB[i]; if (gel(id2, id) == gen_0) continue; gunclone(gel(id2, id)); gel(id2, id) = gen_0; for (k = 1; k < lperm; k++) { long sigmaid = coeff(idealperm, id, k); if (gel(id2, sigmaid) != gen_0) { gunclone(gel(id2, sigmaid)); gel(id2, sigmaid) = 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; } if (i == lv) return 0; 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); 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; 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++) { yes[iyes++] = L_jid[i]; if (iyes > minsFB) break; } } else i = 1; if (iyes <= minsFB) { for ( ; i < lv; i++) { yes[iyes++] = F->perm[i]; if (iyes > minsFB) break; } if (i == lv) return 0; } if (zv_equal(F->subFB, yes)) { if (DEBUGLEVEL) err_printf("*** NOT Changing sub factor base\n"); } else { if (DEBUGLEVEL) err_printf("*** 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; 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)); return is_pm1(gcoeff(y,1,1))? NULL: 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); } static GEN countf(GEN LP) { long i, nP = lg(LP)-1, maxf = pr_get_f(gel(LP, nP)); GEN nbf = const_vecsmall(maxf, 0); nbf[maxf] = 1; for (i = 1; i < nP; i++) { long f = pr_get_f( gel(LP,i) ); nbf[f]++; } return nbf; } 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->cN = R1*c2 + N*c1; S->cD = LOGD - N*c3 - R1*PI/2; S->checkok = 0; } int GRHok(GRHcheck_t *S, double L, double SA, double SB) { if (S->checkok || S->cD + (S->cN + 2*SB) / L - 2*SA < -1e-8) return 1; if (DEBUGLEVEL) err_printf("*** GRH check negative! ***\n"); return 0; } /* Compute FB, LV, iLP + KC*. Reset perm * n2: bound for norm of tested prime ideals (includes be_honest()) * n : bound for p, such that P|p (NP <= n2) used to build relations * Return prod_{p<=n2} (1-1/p) / prod_{Norm(P)<=n2} (1-1/Norm(P)), * close to residue of zeta_K at 1 = 2^r1 (2pi)^r2 h R / (w D) */ static GEN FBgen(FB_t *F, GEN nf, long N, long C2, long C1, GRHcheck_t *S) { byteptr delta = diffptr; long i, p, ip; GEN prim, Res; double L = log((double)C2), SA = 0, SB = 0; maxprime_check((ulong)C2); F->sfb_chg = 0; F->FB = cgetg(C2+1, t_VECSMALL); F->iLP = cgetg(C2+1, t_VECSMALL); F->LV = (GEN*)new_chunk(C2+1); Res = real_1(DEFAULTPREC); prim = icopy(gen_1); i = ip = 0; F->KC = F->KCZ = 0; for (p = 0;;) /* p <= C2 */ { pari_sp av = avma, av1; long f, k, l, m; GEN LP, a, b, nbf; NEXT_PRIME_VIADIFF(p, delta); if (!F->KC && p > C1) { F->KCZ = i; F->KC = ip; } if (p > C2) break; if (DEBUGLEVEL>1) { err_printf(" %ld",p); err_flush(); } prim[2] = p; LP = idealprimedec(nf,prim); av1 = avma; a = b = NULL; nbf = countf(LP); l = lg(nbf); k = 0; /* a/b := (p-1)/p * prod_{LP|p, NP <= C2} NP / (NP-1) */ a = utoi(p-1); b = prim; for (f=1; f C2) break; } k += nb; a = mulii(a, powuu(nor, nb)); b = mulii(b, powuu(nor-1, nb)); if (!S->checkok) { double logp = log((double)p); double logNP = f*logp, q = 1/sqrt((double)nor); double A = logNP * q, B = logNP * A; long M = (long)(L/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; } SA += nb * A; SB += nb * B; } } a = a? divri(mulir(a,Res),b): divru(mulur(p-1,Res),p); affrr(a, Res); avma = av1; if (l == N+1) continue; /* p inert */ /* 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 (f == l) 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 (! F->KC) return NULL; 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]]); } } if (!GRHok(S, L, SA, SB)) return NULL; F->perm = NULL; F->L_jid = NULL; S->checkok = 1; return Res; } /* 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(FB_t *F, long p, long k, GEN nf, GEN m, FACT *fact) { GEN P, LP = F->LV[p]; long j, v, l = lg(LP), ip = F->iLP[p]; for (j=1; j 0 */ k -= v * itos(gel(P,4)); if (!k) return 1; } return 0; } static int divide_p_id(FB_t *F, long p, long k, GEN nf, GEN I, FACT *fact) { GEN P, LP = F->LV[p]; long j, v, l = lg(LP), ip = F->iLP[p]; for (j=1; j 0 */ k -= v * itos(gel(P,4)); if (!k) return 1; } return 0; } static int divide_p_quo(FB_t *F, long p, long k, GEN nf, GEN I, GEN m, FACT *fact) { GEN P, LP = F->LV[p]; long j, v, l = lg(LP), ip = F->iLP[p]; for (j=1; j 0 */ k -= v * itos(gel(P,4)); if (!k) return 1; } return 0; } /* is *N > 0 a smooth rational integer wrt F ? (put the exponents in *ex) */ static int smooth_int(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) { if (!m) return divide_p_id (F,p,k,nf,I,fact); if (!I) return divide_p_elt(F,p,k,nf,m,fact); return divide_p_quo(F,p,k,nf,I,m,fact); } /* Let x = m if I == NULL, * I if m == NULL, * m/I otherwise. * Can we factor the integral ideal x ? N = Norm x > 0 [DESTROYED] */ static long can_factor(FB_t *F, GEN nf, GEN I, GEN m, GEN N, FACT *fact) { GEN ex; long i; fact[0].pr = 0; if (is_pm1(N)) return 1; if (!smooth_int(F, &N, &ex)) return 0; for (i=1; i<=ex[0]; i++) if (ex[i] && !divide_p(F, F->FB[i], ex[i], nf, I, m, fact)) return 0; return is_pm1(N) || divide_p(F, itos(N), 1, nf, I, m, fact); } /* 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(norm_by_embed(r1, RgM_RgC_mul(M,m)), NI); /* ~ N(m/I) */ N = grndtoi(N, &e); if (e > -1) return 0; return can_factor(F, nf, I, m, absi(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(talker,"not a vector/matrix in cleanarch"); 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 get too big */ static long expgexpo(GEN x) { long i,j,e, E = - (long)HIGHEXPOBIT; GEN p1; for (i=1; iE) E=e; } return E; } 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 20) { *pte = LONG_MAX; return not_given(fupb_LARGE); } if (prec <= 0) prec = gprecision(A); y = RgM_solve_realimag(M, gexp(y,prec)); if (!y) return not_given(fupb_PRECI); y = grndtoi(y, &e); *pte = -e; if (e >= 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; /* try without reduction if x is small. * N.B. can_factor() destroys its NI argument */ if (gexpo(gcoeff(x,1,1)) < 100 && can_factor(F, nf, x, NULL, icopy(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*)stackmalloc((F.KC+1)*sizeof(FACT)); /* loop up to min(maxprime, BOUND) */ for (av=avma, p=2; p < bound; avma=av) { GEN vP = idealprimedec(bnf, utoipos(p)); long i, l = lg(vP); if (DEBUGLEVEL>1) err_printf("*** p = %lu\n",p); /* loop through all P | p if ramified, all but one otherwise */ if (umodiu(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 (p <= pmax && (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); } NEXT_PRIME_VIADIFF(p, d); } if (boundp == bound) { avma = av0; return; } /* finish looping up to BOUND */ pari_warn(warner,"Zimmert's bound is large (%Pd), certification will take a long time", BOUND); gp = utoipos(bound); for (av=avma; cmpii(gp, BOUND) < 0; gp = gerepileuptoint(av, nextprime(addis(gp,1)))) { GEN vP = idealprimedec(bnf, gp); long i, l = lg(vP); if (DEBUGLEVEL>1) err_printf("*** p = %Pu\n",gp); /* loop through all P | p if ramified, all but one otherwise */ if (!dvdii(dK,gp)) 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 (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(typeer,"famat_to_arch"); if (lg(fa) == 1) return triv_arch(nf); g = gel(fa,1); e = gel(fa,2); l = lg(e); for (i=1; i R1) * Return NULL if precision problem, and set *emb to the embeddings of x */ GEN get_arch_real(GEN nf, GEN x, GEN *emb, long prec) { long i, lx, R1; GEN v, t; if (typ(x) == t_MAT) return famat_get_arch_real(nf,x,emb,prec); x = nf_to_scalar_or_basis(nf,x); if (typ(x) != t_COL) return scalar_get_arch_real(nf, gtofp(x,prec), emb); R1 = nf_get_r1(nf); x = RgM_RgC_mul(nf_get_M(nf), x); lx = lg(x); v = cgetg(lx,t_COL); for (i=1; i<=R1; i++) { t = gabs(gel(x,i),prec); if (low_prec(t)) return NULL; gel(v,i) = glog(t,prec); } for ( ; i< lx; i++) { t = gnorm(gel(x,i)); if (low_prec(t)) return NULL; gel(v,i) = glog(t,prec); } *emb = x; return v; } GEN init_red_mod_units(GEN bnf, long prec) { GEN s = gen_0, p1,s1,mat, logfu = bnf_get_logfu(bnf); long i,j, RU = lg(logfu); if (RU == 1) return NULL; mat = cgetg(RU,t_MAT); for (j=1; j 0) s = s1; } s = gsqrt(gmul2n(s,RU),prec); if (expo(s) < 27) s = utoipos(1UL << 27); return mkvec2(mat, s); } /* z computed above. Return unit exponents that would reduce col (arch) */ GEN red_mod_units(GEN col, GEN z) { long i,RU; GEN x,mat,N2; if (!z) return NULL; mat= gel(z,1); N2 = gel(z,2); RU = lg(mat); x = cgetg(RU+1,t_COL); 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(precer, "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 (!gequal1(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) { long p = 2 + maxss(1, (nf_get_prec(nf)-2) / 2); if (typ(logN) != t_REAL || gprecision(rx) > p) { avma = av; return cgetg(1,t_COL); } /* not a precision problem */ } else { ex = RgM_solve(rlog, rx); if (ex) { ex = grndtoi(ex, &e); if (gequal0(gel(ex,RU)) && e < -4) break; } } } if (i == 1) prec = MEDDEFAULTPREC + divsBIL( gexpo(x) ); else { if (i > 4) pari_err(precer,"bnfisunit"); prec = (prec-1)<<1; } 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++) C[i] = 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) { const ulong p = 27449UL; 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*(p-c[i])) % 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], p); /* Cleanup a */ for (i = k; i-- > 1; ) { long j, ai = a[i]; c = gel(basis, i); if (!ai || !c[i]) continue; ai = p-ai; for (j = 1; j < i; j++) if (c[j]) a[j] = (a[j] + ai*c[j]) % 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) { if (in_rnd_rel) dbg_newrel(cache); else dbg_rel(rel - cache->base, R); } } 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; if (DEBUGLEVEL>1) err_printf("%ld: 1", id); powPgen(nf, gel(F->LP, id), &id2, a); gel(F->id2, id) = gclone(id2); for (k = 1; k < naut; k++) { long sigmaid = coeff(idealperm, id, k); GEN aut = gel(auts, k), invaut = gel(auts, F->invs[k]); if (gel(F->id2, sigmaid) == gen_0) { long lid2; GEN sigmaid2 = cgetg_copy(id2, &lid2); if (DEBUGLEVEL>1) err_printf("%ld: automorphism\n", sigmaid); for (l = 1; l < lid2; l++) { GEN id2l = gel(id2, l); gel(sigmaid2, l) = mkvec2(gel(id2l, 1), ZM_mul(ZM_mul(aut, gel(id2l, 2)), invaut)); } gel(F->id2, sigmaid) = gclone(sigmaid2); } } } } 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; } } 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), R1 = nf_get_r1(nf), prec = nf_get_prec(nf); const long BMULT = 8; const long maxtry_DEP = 20, maxtry_FACT = 500; double *y, *z, **q, *v, BOUND; pari_sp av; GEN x, 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#### Looking for %ld relations (small norms)\n", cache->end - last); } 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 = 3 + (long)ceil( (N/2. * ((N-1)/2.* log(4./3) + log(BMULT/(double)N)) + log(LIMC2) + LOGD/2) / (BITS_IN_LONG * LOG2)); /* enough to compute norms */ if (precbound < prec) M = gprec_w(M, precbound); minim_alloc(N+1, &q, &x, &y, &z, &v); for (av = avma; --noideal; avma = av) { GEN r, u, gx, ideal=gel(F->LP,L_jid[noideal]), inc=const_vecsmall(N, 1); long j, k, skipfirst, nbrelideal = 0, dependent = 0, try_factor = 0; pari_sp av2; if (DEBUGLEVEL>1) err_printf("\n*** Ideal no %ld: %Ps\n", L_jid[noideal], vecslice(ideal,1,4)); if (p0) ideal = idealmul(nf, p0, ideal); else ideal = idealhnf_two(nf, ideal); u = ZM_lll(ZM_mul(F->G0, ideal), 0.99, LLL_IM); ideal = ZM_mul(ideal,u); /* approximate T2-LLL reduction */ r = Q_from_QR(RgM_mul(G, ideal), prec); /* Cholesky for T2 | ideal */ if (!r) pari_err(bugparier, "small_norm (precision too low)"); skipfirst = ZV_isscalar(gel(ideal,1))? 1: 0; /* 1 probable */ for (k=1; k<=N; k++) { v[k] = gtodouble(gcoeff(r,k,k)); for (j=1; j3) err_printf("v[%ld]=%.4g ",k,v[k]); } BOUND = mindd(BMULT * v[1], 2 * (v[2] + v[1]*q[1][2]*q[1][2])); /* BOUND at most BMULT 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; y[N] = z[N] = 0; x[N] = 0; for (av2 = avma;; avma = av2, step(x,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; 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]; if (l <= skipfirst && !y[1]) fl = 1; x[l] = (long)floor(-z[l] + 0.5); k = l; } for(;; step(x,y,inc,k)) { if (!fl) { p = (double)x[k] + z[k]; if (y[k] + p*p*v[k] <= BOUND) break; step(x,y,inc,k); p = (double)x[k] + z[k]; if (y[k] + p*p*v[k] <= BOUND) break; } fl = 0; inc[k] = 1; if (++k > N) goto ENDIDEAL; } } while (k > 1); /* element complete */ if (zv_content(x) !=1) continue; /* not primitive */ gx = ZM_zc_mul(ideal,x); if (ZV_isscalar(gx)) continue; { GEN Nx, xembed = RgM_RgC_mul(M, gx); long e; nbsmallnorm++; if (++try_factor > maxtry_FACT) goto ENDIDEAL; Nx = grndtoi(norm_by_embed(R1,xembed), &e); if (e >= 0) { if (DEBUGLEVEL > 1) { err_printf("+"); err_flush(); } continue; } setabssign(Nx); if (!can_factor(F, nf, NULL, gx, Nx, fact)) { if (DEBUGLEVEL > 1) { err_printf("."); err_flush(); } continue; } } /* smooth element */ R = set_fact(F, fact, NULL, &nz); /* make sure we get maximal rank first, then allow all relations */ if (add_rel(cache, F, R, nz, gx, 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++; if (cache->last >= cache->end) goto END; /* we have enough */ if (++nbrelideal == nbrelpid) break; } ENDIDEAL: if (DEBUGLEVEL>1) timer_printf(&T, "for this ideal"); } END: if (DEBUGLEVEL) { if (cache->last != last) err_printf("\n"); timer_printf(&T, "small norm relations"); err_printf(" small norms gave %ld relations.\n", cache->last - last); if (nbsmallnorm) 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, GEN auts, FACT *fact) { pari_timer T; GEN L_jid = F->L_jid; GEN ex, baseideal, m1; const long nbG = lg(F->vecG)-1, lgsub = lg(F->subFB), l_jid = lg(L_jid); long jlist; pari_sp av; /* will compute P[ L_jid[i] ] * (random product from subFB) */ if (DEBUGLEVEL) { long d = cache->end - cache->last; timer_start(&T); err_printf("\n(more relations needed: %ld)\n", d > 0? d: 1); if (l_jid <= F->orbits) err_printf("looking hard for %Ps\n",L_jid); } ex = cgetg(lgsub, t_VECSMALL); baseideal = get_random_ideal(F, nf, ex); baseideal = red(nf, baseideal, F->G0, &m1); if (baseideal) baseideal = idealhnf_two(nf, baseideal); for (av = avma, jlist = 1; jlist < l_jid; jlist++, avma = av) { long jid = L_jid[jlist]; GEN Nideal, ideal; pari_sp av1; long j, l; if (DEBUGLEVEL>1) err_printf("(%ld)", jid); /* If subFB is not Galois-stable, all ideals in the orbit of jid are not * equivalent (subFB is probably not Galois stable) */ l = random_Fl(lg(auts)); if (l) jid = coeff(F->idealperm, jid, l); ideal = gel(F->LP,jid); if (baseideal) ideal = idealmul_HNF(nf, baseideal, ideal); else ideal = idealhnf_two(nf, ideal); Nideal = ZM_det_triangular(ideal); 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,Nideal,m,fact)) { if (DEBUGLEVEL>1) { err_printf("."); err_flush(); } continue; } /* can factor ideal, record relation */ add_to_fact(jid, 1, fact); R = set_fact(F, fact, ex, &nz); switch (add_rel(cache, F, R, nz, nfmul(nf, m, m1), 1)) { case -1: /* forget it */ if (DEBUGLEVEL>1) dbg_cancelrel(jid,j,R); continue; case 0: break; } 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) timer_printf(&T, "for remaining ideals"); } /* remark: F->KCZ changes if be_honest() fails */ static int be_honest(FB_t *F, GEN nf, FACT *fact) { GEN P, ideal, Nideal, m; long ex, i, j, J, k, iz, nbtest; long nbG = lg(F->vecG)-1, lgsub = lg(F->subFB), KCZ0 = F->KCZ; 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 ]); } av = avma; for (iz=F->KCZ+1; iz<=F->KCZ2; iz++, avma = av) { long p = F->FB[iz]; if (DEBUGLEVEL>1) err_printf("%ld ", p); 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--; for (j=1; jsubFB[i]; ex = random_bits(RANDOM_BITS); if (ex) ideal = idealmul_HNF(nf,ideal, gmael(F->id2,id,ex)); } ideal = remove_content(ideal); Nideal = ZM_det_triangular(ideal); for (av1 = avma, k = 1; k <= nbG; k++, avma = av1) { m = idealpseudomin_nonscalar(ideal, gel(F->vecG,k)); if (factorgen(F,nf,ideal,Nideal, m,fact)) break; } avma = av2; if (k <= nbG) break; if (++nbtest > 50) { pari_warn(warner,"be_honest() failure on prime %Ps\n", P[j]); return 0; } } } F->KCZ++; /* SUCCESS, "enlarge" factorbase */ } if (DEBUGLEVEL>1) err_printf("\n"); 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 = lg(gel(A,1));; 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, Im_expo, 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; if (lg(mdet) < RU) { if (DEBUGLEVEL) err_printf("Unit group rank <= %ld < %ld\n",lg(mdet)-1, RU); *pneed = RU - (lg(mdet)-1); avma = av; return NULL; } 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 */ Im_expo = cgetg(RU+1, t_VECSMALL); /* ... and exponents (from renormalize) */ /* N.B: d[1] = 1, corresponding to T above */ gel(Im_mdet, 1) = T; Im_expo[1] = 0; 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; CATCH(precer) { y = NULL; } TRY { y = bestappr(x,k); } 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_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,3)); return fupb_PRECI; } L = Q_muli_to_int(lambda, den); H = ZM_hnf(L); r = lg(H)-1; /* tentative regulator */ R = gmul(*ptkR, gdiv(ZM_det_triangular(H), powiu(den, r))); c = gmul(R,z); /* should be n (= 1 if we are done) */ if (DEBUGLEVEL) { err_printf("\n#### Tentative regulator : %Ps\n", gprec_w(R,3)); err_printf("\n ***** check = %Ps\n",gprec_w(c,3)); } 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_hnfremdiv(U, D, &Y); Uir = ZM_hnfremdiv(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; i1) err_printf("*%ld ",j); gel(ma,j) = gerepileupto(btop, y); continue; } y = isprincipalfact_or_fail(bnf, C, pFB, ex); if (typ(y) != t_INT) { if (DEBUGLEVEL>1) err_printf("%ld ",j); gel(ma,j) = gerepileupto(btop,gel(y,2)); continue; } prec = itos(y); j--; /* will retry the same element in next loop */ if (DEBUGLEVEL) pari_warn(warnprec,"makematal",prec); nf = nfnewprec_shallow(nf,prec); bnf = Buchall(nf, nf_FORCE, prec); setrand(c); } if (DEBUGLEVEL>1) err_printf("\n"); return ma; } #define MATAL 1 #define CYCGEN 2 GEN check_and_build_cycgen(GEN bnf) { return check_and_build_obj(bnf, CYCGEN, &makecycgen); } GEN check_and_build_matal(GEN bnf) { return check_and_build_obj(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, lg(mun[1])-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 += (e>>TWOPOTBITS_IN_LONG); } 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 = (prec-1)<<1; 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->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->lead = 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) = gen_0; /* dummy: we MUST have lg(bnf) != lg(nf) */ 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(typeer,"bnfmake"); 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(precer, "bnfmake"); prec = gprecision(ro); matal = check_and_build_matal(sbnf); C = get_archclean(nf,matal,prec,0); if (!C) pari_err(precer, "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(typeer,"bnfinit"); 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(flagerr,"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 (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 = lg(gel(M, 1)), 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(M); 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; for (i = 1; i < r1plusr2; i++) { 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 list = F->L_jid ? F->L_jid : F->perm, present = zero_Flv(F->KC); long i, j, imax = lg(F->L_jid); GEN minidx = F->minidx, idx = cgetg(lg(list), t_VECSMALL); for (i = j = 1; i < imax; i++) { long id = minidx[list[i]]; if (!present[id]) { idx[j++] = id; present[id] = 1; } } setlg(idx, j); return gerepileuptoleaf(av, idx); } GEN Buchall_param(GEN P, double cbach, double cbach2, long nbrelpid, long flun, long prec) { const long MAXRELSUP = 50, SFB_MAX = 3; pari_timer T; pari_sp av0 = avma, av, av2; long PRECREG, N, R1, R2, RU, LIMC, LIMC2, zc, i; long nreldep, sfb_trials, need, old_need = -1, precdouble = 0, precadd = 0; long done_small; double lim, drc, LOGD, LOGD2; GEN zu, nf, D, A, W, R, Res, z, h, PERM, fu = NULL /*-Wall*/; GEN res, L, resc, B, C, C0, lambda, dep, clg1, clg2, Vbase; GEN auts, cyclic, small_mult; const char *precpb = NULL; const long minsFB = 3, RELSUP = 5; int FIRST = 1; 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); } } 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(talker,"Bach constant <= 0 in buch"); /* resc ~ sqrt(D) w / 2^r1 (2pi)^r2 = hR / Res(zeta_K, s=1) */ resc = gdiv(mulri(gsqrt(D,DEFAULTPREC), gel(zu,1)), gmul2n(powru(mppi(DEFAULTPREC), R2), RU)); av = avma; cache.base = NULL; F.subFB = NULL; init_GRHcheck(&GRHcheck, N, R1, LOGD); START: if (DEBUGLEVEL) timer_start(&T); do { if (!FIRST) cbach = check_bach(cbach,12.); FIRST = 0; avma = av; if (cache.base) delete_cache(&cache); if (F.subFB) delete_FB(&F); LIMC = (long)(cbach*LOGD2); if (LIMC < 20) { LIMC = 20; cbach = (double)LIMC / LOGD2; } LIMC2 = maxss(3 * N, (long)(cbach2*LOGD2)); if (LIMC2 < LIMC) LIMC2 = LIMC; if (DEBUGLEVEL) { err_printf("LIMC = %ld, LIMC2 = %ld\n",LIMC,LIMC2); } Res = FBgen(&F, nf, N, LIMC2, LIMC, &GRHcheck); } while (!Res || !subFBgen(&F,nf,auts,cyclic,mindd(lim,LIMC2) + 0.5,minsFB)); if (DEBUGLEVEL) timer_printf(&T, "factorbase (#subFB = %ld) and ideal permutations", lg(F.subFB)-1); fact = (FACT*)stackmalloc((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); F.id2 = zerovec(F.KC); small_mult = zero_Flv(F.KC); done_small = 0; R = NULL; av2 = avma; init_rel(&cache, &F, RELSUP + RU-1); /* trivial relations */ need = cache.end - cache.last; W = NULL; sfb_trials = nreldep = 0; do { do { if (need > 0) { long oneed = cache.end - cache.last; /* Test below can be true if elts != NULL */ 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 && (!R || lg(W)>1) && cache.last < cache.base + 2*F.KC /* heuristic */) { pari_sp av3 = avma; GEN p0 = NULL, L_jid = F.L_jid, aut0 = auts; if (R) { /* 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; /* We need lg(W)-1 relations. */ F.L_jid = vecslice(F.perm, 1, lg(W) - 1); cache.end = cache.last + lg(W) - 1; /* Lie to the add_rel subsystem: pretend we miss relations involving * the primes generating the class group (and only those). */ cache.missing = lg(W) - 1; for (l = 1; l < lg(W); l++) mael(cache.basis, F.perm[l], F.perm[l]) = 0; /* Lie to the small_norm subsystem: pretend there are no automorphisms * (automorphisms tend to create lattices that are twice the size of * the full lattice: if a relation is p1+p2=0 where p1 and p2 are in * the same odd-sized orbit, then the images of this relation will * lead to p1=...=pn and 2p1=0). */ auts = cgetg(1, t_VEC); } if (done_small) { long j = 0, lim; for (i = F.KC; i >= 1; i--) if (!small_mult[j = F.perm[i]]) break; small_mult[j]++; p0 = gel(F.LP, j); lim = F.minidx[j]; if (!R) { /* Prevent considering both P_iP_j and P_jP_i in small_norm */ for (i = j = 1; i < lg(F.L_jid); i++) if (F.L_jid[i] >= lim) F.L_jid[j++] = F.L_jid[i]; setlg(F.L_jid, j); } } if (lg(F.L_jid) > 1) small_norm(&cache, &F, nf, nbrelpid, LOGD, LIMC2, fact, p0); avma = av3; if (R) { long l; auts = aut0; F.L_jid = L_jid; cache.end = cache.last + need; for (l = 1; l < lg(W); l++) mael(cache.basis, F.perm[l], F.perm[l]) = 1; cache.missing = 0; } else { F.L_jid = F.perm; need = 0; } done_small++; F.sfb_chg = 0; } if (need > 0) { /* Random relations */ if (DEBUGLEVEL) err_printf("\n#### Looking for random relations\n"); if (++nreldep > MAXRELSUP) { if (++sfb_trials > SFB_MAX && cbach < 2) goto START; F.sfb_chg = sfb_INCREASE; } if (F.sfb_chg) { if (!subFB_change(&F)) goto START; nreldep = 0; } if (F.newpow) { if (DEBUGLEVEL) timer_start(&T); powFBgen(&cache, &F, nf, auts); if (DEBUGLEVEL) timer_printf(&T, "powFBgen"); } if (!F.sfb_chg) rnd_rel(&cache, &F, nf, auts, fact); F.L_jid = F.perm; } if (precpb) { pari_sp av3 = avma; GEN nf0 = nf; if (precadd) { PRECREG += precadd; precadd = 0; } else PRECREG = (PRECREG<<1)-2; 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); avma = av3; 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 */ } { /* 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; timer_start(&T); 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, lg(F.subFB)-1); if (DEBUGLEVEL) timer_printf(&T, "hnfspec [%ld x %ld]", lg(F.perm)-1, lg(mat)-1); } else { W = hnfadd_i(W, F.perm, &dep, &B, &C, mat, emb); if (DEBUGLEVEL) timer_printf(&T, "hnfadd (%ld + %ld)", lg(mat)-1, lg(dep)-1); } gerepileall(av2, 4, &W,&C,&B,&dep); cache.chk = cache.last; need = lg(dep)>1? lg(dep[1])-1: lg(B[1])-1; /* FIXME: replace by err(bugparier,"") */ 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)) { 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 && !F.newpow) F.sfb_chg = sfb_CHANGE; 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) { F.L_jid = gcopy(F.perm); lswap(F.L_jid[1], F.L_jid[1+(nreldep%(lg(W) - 1))]); } else F.L_jid = F.perm; } } } while (need); A = vecslice(C, 1, zc); /* cols corresponding to units */ R = compute_multiple_of_R(A, RU, N, &need, &lambda); 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); z = mulrr(Res, resc); /* ~ hR if enough relations, a multiple otherwise */ switch (compute_R(lambda, divir(h,z), &L, &R)) { case fupb_RELAT: need = 1; /* not enough relations */ continue; case fupb_PRECI: /* prec problem unless we cheat on Bach constant */ if ((precdouble&7) == 7 && cbach<=2) goto START; precpb = "compute_R"; continue; } /* DONE */ if (DEBUGLEVEL) timer_start(&T); if (F.KCZ2 > F.KCZ) { if (F.sfb_chg && !subFB_change(&F)) goto START; if (F.newpow) powFBgen(NULL, &F, nf, auts); if (!be_honest(&F, nf, fact)) goto START; if (DEBUGLEVEL) timer_printf(&T, "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 = (DEFAULTPREC-2) + divsBIL( gexpo(AU) ) - 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(talker, "bnfinit: fundamental units too large"); if (e < 0) precadd = (DEFAULTPREC-2) + divsBIL( (-e) ); 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 = (DEFAULTPREC-2) + divsBIL( gexpo(C0) ) - gprecision(C0); if (precadd <= 0) precadd = 1; precpb = "cleanarch"; } } while (need || precpb); delete_cache(&cache); delete_FB(&F); 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.5.5/src/basemath/hnf_snf.c0000644000175000017500000017501112147140046015250 0ustar billbill/* $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. */ #include "pari.h" #include "paripriv.h" /**************************************************************/ /** **/ /** HERMITE NORMAL FORM REDUCTION **/ /** **/ /**************************************************************/ GEN mathnf0(GEN x, long flag) { if (typ(x)!=t_MAT) pari_err(typeer,"mathnf0"); RgM_check_ZM(x, "mathnf0"); switch(flag) { case 0: return ZM_hnf(x); case 1: return hnfall(x); case 3: return hnfperm(x); case 4: return hnflll(x); default: pari_err(flagerr,"mathnf"); } return NULL; /* not reached */ } /*******************************************************************/ /* */ /* SPECIAL HNF (FOR INTERNAL USE !!!) */ /* */ /*******************************************************************/ static int count(GEN mat, long row, long len, long *firstnonzero) { long j, n = 0; for (j=1; j<=len; j++) { long p = mael(mat,j,row); if (p) { if (labs(p)!=1) return -1; n++; *firstnonzero=j; } } return n; } static int count2(GEN mat, long row, long len) { long j; for (j=len; j; j--) if (labs(mael(mat,j,row)) == 1) return j; return 0; } static GEN hnffinal(GEN matgen,GEN perm,GEN* ptdep,GEN* ptB,GEN* ptC) { GEN p1,p2,U,H,Hnew,Bnew,Cnew,diagH1; GEN B = *ptB, C = *ptC, dep = *ptdep, depnew; pari_sp av, lim; long i,j,k,s,i1,j1,zc; long co = lg(C); long col = lg(matgen)-1; long lnz, nlze, lig; if (col == 0) return matgen; lnz = lg(matgen[1])-1; /* was called lnz-1 - nr in hnfspec */ nlze = lg(dep[1])-1; lig = nlze + lnz; /* H: lnz x lnz [disregarding initial 0 cols], U: col x col */ H = ZM_hnflll(matgen, &U, 0); H += (lg(H)-1 - lnz); H[0] = evaltyp(t_MAT) | evallg(lnz+1); /* Only keep the part above the H (above the 0s is 0 since the dep rows * are dependent from the ones in matgen) */ zc = col - lnz; /* # of 0 columns, correspond to units */ if (nlze) { dep = ZM_mul(dep,U); dep += zc; } diagH1 = new_chunk(lnz+1); /* diagH1[i] = 0 iff H[i,i] != 1 (set later) */ av = avma; lim = stack_lim(av,1); Cnew = cgetg(co, typ(C)); setlg(C, col+1); p1 = gmul(C,U); for (j=1; j<=col; j++) Cnew[j] = p1[j]; for ( ; j1) 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]) p1[++j1] = p2[i]; else p2[++i1] = p2[i]; for (i=i1+1; i<=lnz; i++) p2[i] = 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); /* = lg(mat0[1]) */ 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 && lg(C[1]) > 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++) p2[i] = 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, t_MAT); for (j = 1 ; j <= l; j++) { MAT[j] = 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 = lg(x[1]); *ptperm = perm = identity_perm(ly-1); z = cgetg(lx,t_MAT); for (i=1; i 1 && lg((*ptC)[1]) > 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 = 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)); } } /* reduce A[i,j] mod A[i,j0] for j=j0+1... via column operations */ static void ZM_reduce(GEN A, GEN U, long i, long j0) { long j, lA = lg(A); GEN d = gcoeff(A,i,j0); if (signe(d) < 0) { ZV_neg_inplace(gel(A,j0)); if (U) ZV_togglesign(gel(U,j0)); d = gcoeff(A,i,j0); } 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))); } /* 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, m, n = lg(A)-1, i, j, k, li, def, ldef; GEN a; if (!n) return cgetg(1,t_MAT); av = avma; A = RgM_shallowcopy(A); m = lg(A[1])-1; lim = stack_lim(av,1); def = n; ldef = (m>n)? m-n: 0; for (li=m; li>ldef; li--) { for (j=def-1; j; j--) { 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); } } if (remove) { /* remove 0 columns */ for (i=1,j=1; j<=n; j++) if (!ZV_equal0(gel(A,j))) A[i++] = A[j]; setlg(A,i); } 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 b, 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(z[i])) gel(z,i) = modii(gel(z,i), p); } else { for (i = 1; i <= k; i++) if (signe(z[i])) gel(z,i) = modii(negi(gel(z,i)), p); } } else { for (i = 1; i <= k; i++) if (signe(z[i])) gel(z,i) = Fp_mul(u,gel(z,i), p); } } static void FpV_red_part_ip(GEN z, GEN p, long k) { long i; for (i = 1; i <= k; i++) gel(z,i) = modii(gel(z,i), p); } /* 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(GEN x, GEN dm, long flag) { pari_sp av0 = avma, av, lim; const long modid = (flag & hnf_MODID); const long center = (flag & hnf_CENTER); long li, co, i, j, k, def, ldef, ldm; GEN a, b, p1, p2, u, dm2; co = lg(x); if (co == 1) return cgetg(1,t_MAT); li = lg(x[1]); dm2 = shifti(dm, -1); av = avma; lim = stack_lim(av,1); x = RgM_shallowcopy(x); ldef = 0; if (li > co) { ldef = li - co; if (!modid) pari_err(talker,"nb lines > nb columns in ZM_hnfmod"); } /* To prevent coeffs explosion, only reduce mod dm when lg() > ldm */ ldm = lgefint(dm); for (def = co-1,i = li-1; i > ldef; i--,def--) { gcoeff(x,i,def) = centermodii(gcoeff(x,i,def), dm,dm2); for (j = def-1; j; j--) { gcoeff(x,i,j) = centermodii(gcoeff(x,i,j), dm,dm2); a = gcoeff(x,i,j); if (!signe(a)) continue; k = (j==1)? def: j-1; gcoeff(x,i,k) = centermodii(gcoeff(x,i,k), dm,dm2); ZC_elem(a,gcoeff(x,i,k), x,NULL, j,k); p1 = gel(x,j); p2 = gel(x,k); for (k = 1; k < i; k++) { if (lgefint(p1[k]) > ldm) gel(p1,k) = centermodii(gel(p1,k), dm,dm2); if (lgefint(p2[k]) > ldm) gel(p2,k) = centermodii(gel(p2,k), dm,dm2); } 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 (modid && !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++) a[k] = x[k]; gel(a,k++) = Rg_col_ei(dm, li-1, i); for ( ; k <= co; k++) a[k] = x[k-1]; ldef--; if (ldef < 0) ldef = 0; co++; def++; x = a; } } x += co - li; if (modid) { /* w[li] is an accumulator, discarded at the end */ GEN w = cgetg(li+1, t_MAT); for (i = li-1; i > ldef; i--) w[i] = x[i]; for ( ; i > 0; i--) gel(w,i) = Rg_col_ei(dm, li-1, i); x = w; for (i = li-1; i > 0; i--) { /* check that dm*Id \subset L + add up missing dm*Id components */ GEN d, c; d = bezout(gcoeff(x,i,i),dm, &u,NULL); gcoeff(x,i,i) = d; if (is_pm1(d)) { FpV_Fp_mul_part_ip(gel(x,i), u, dm, i-1); continue; } c = cgetg(li, t_COL); for (j = 1; j < i; j++) gel(c,j) = remii(gcoeff(x,j,i),d); for ( ; j ldef; 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_ip(gel(x,li), dm, j-1); FpV_red_part_ip(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 = dm; 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 (modid) b = const_vec(li-1, dm); else { /* 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-2; i > 0; i--) { GEN diag = gcoeff(x,i,i); ldm = lgefint(dm[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) 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 gerepilecopy(av0, x); } 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(dm)!=t_INT) pari_err(typeer,"allhnfmod"); if (typ(x)!=t_MAT) pari_err(typeer,"allhnfmod"); RgM_check_ZM(x, "allhnfmod"); return signe(dm)? ZM_hnfmodall(x, dm, flag): ZM_hnf(x); } GEN hnfmod(GEN x, GEN d) { return allhnfmod(x, d, 0); } GEN hnfmodid(GEN x, GEN 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; } /* 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; } 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(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(A[n-1]) < 0) { togglesign_safe(&gel(A,n-1)); ZV_togglesign(gel(B,n-1)); } return gerepilecopy(av, mkvec2(gel(A,n-1), B)); } /* 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 = lg(A[1])-1; c = const_vecsmall(m, 0); l = const_vecsmall(n, 0); 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; n = lg(A)-1; if (!n) { if (ptB) *ptB = cgetg(1,t_MAT); return cgetg(1,t_MAT); } m = lg(A[1])-1; c = const_vecsmall(m, 0); 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(consister,"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 = lg(A[1])-1; /* 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(typeer,"hnf_invimage"); 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(typeer,"hnf_invimage"); 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 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 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(typeer,"smith"); 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(typeer,"smithall"); 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) - bit_accuracy(gprecision(r))) ) return k; } return 0; } 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(typeer,"gsmithall"); if (vx==NO_VARIABLE) return all? smithall(x): smith(x); n = lg(x)-1; if (!n) return trivsmith(all); if (lg(x[1]) != n+1) pari_err(mattype1,"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 T = gcoeff(x,k,k); if (is_RgX(T,vx) && signe(T)) { GEN d = leading_term(T); while (gequal0(d) || ( typ(d) == t_REAL && lg(d) == 3 && gexpo(T) - expo(d) > (long)BITS_IN_LONG)) { T = normalizepol_lg(T, lg(T)-1); if (!signe(T)) { gcoeff(x,k,k) = T; continue; } d = leading_term(T); } if (!gequal1(d)) { gcoeff(x,k,k) = RgX_Rg_div(T,d); if (all) gel(V,k) = RgC_Rg_div(gel(V,k), d); } } } 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(flagerr,"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(talker, "accuracy lost in matfrobenius"); for (j=0; j n) pari_err(talker, "accuracy lost in matfrobenius"); gcoeff(M,k,i) = gen_1; for (j=1; j2) pari_err(flagerr,"matfrobenius"); A = matsnf0(M_x,3); D = smithclean(RgM_diagonal_shallow(gel(A,3))); if (prod_degree(D) != n) pari_err(talker, "accuracy lost in 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.5.5/src/basemath/F2x.c0000644000175000017500000004426212147140046014271 0ustar billbill/* $Id$ 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 sv) { return mpodd(x) ? pol1_F2x(sv): pol0_F2x(sv); } GEN ZX_to_F2x(GEN x) { long l=nbits2prec(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*/ 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); avma = av; ly = lx + v; x += lx; y = new_chunk(ly) + ly; /*cgetg could overwrite x!*/ 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]<>dc; } if (r) x[i+dl] ^= r; } else for(i=2; i=0 */ static GEN F2x_shift(GEN y, ulong d) { ulong db, dl=dvmduBIL(d, &db); long i, ly = lg(y), lx = ly+dl+(!!db), ld = 2+db; GEN x = cgetg(lx, t_VECSMALL); for(i=2; i>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(gdiver); 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 = const_vecsmall(lg(x)-lg(y)+2, 0); 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; } GEN F2x_deriv(GEN z) { const ulong mask = ULONG_MAX/3UL; long i,l = lg(z); GEN x = cgetg(l, t_VECSMALL); x[1] = z[1]; for (i=2; 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; } GEN F2xq_mul(GEN x,GEN y,GEN pol) { GEN z = F2x_mul(x,y); return F2x_rem(z,pol); } GEN F2xq_sqr(GEN x,GEN pol) { GEN z = F2x_sqr(x); return F2x_rem(z,pol); } GEN F2xq_invsafe(GEN x, GEN T) { GEN V, z = F2x_extgcd(T, x, NULL, &V); if (F2x_degree(z)) return NULL; return V; } GEN F2xq_inv(GEN x,GEN T) { pari_sp av=avma; GEN U = F2xq_invsafe(x, T); if (!U) pari_err(gdiver); return gerepileuptoleaf(av, U); } GEN F2xq_div(GEN x,GEN y,GEN T) { pari_sp av = avma; return gerepileuptoleaf(av, F2xq_mul(x,F2xq_inv(y,T),T)); } static GEN _F2xq_sqr(void *data, GEN x) { GEN pol = (GEN) data; return F2xq_sqr(x, pol); } static GEN _F2xq_mul(void *data, GEN x, GEN y) { GEN pol = (GEN) data; return F2xq_mul(x,y, pol); } GEN F2xq_pow(GEN x, GEN n, GEN pol) { pari_sp av=avma; GEN y; if (!signe(n)) return pol1_F2x(x[1]); if (is_pm1(n)) /* +/- 1 */ return (signe(n) < 0)? F2xq_inv(x,pol): vecsmall_copy(x); if (signe(n) < 0) x = F2xq_inv(x,pol); y = gen_pow(x, n, (void*)pol, &_F2xq_sqr, &_F2xq_mul); return gerepileupto(av, y); } /* generates the list of powers of x of degree 0,1,2,...,l*/ GEN F2xq_powers(GEN x, long l, GEN T) { GEN V = cgetg(l+2,t_VEC); long i, v = T[1]; gel(V,1) = pol1_F2x(v); if (l==0) return V; gel(V,2) = vecsmall_copy(x); if (l==1) return V; gel(V,3) = F2xq_sqr(x,T); if ((F2x_degree(x)<<1) < F2x_degree(T)) { for(i = 4; i < l+2; i++) gel(V,i) = F2xq_mul(gel(V,i-1),x,T); } else { for(i = 4; i < l+2; i++) { gel(V,i) = (i&1)? F2xq_sqr(gel(V, (i+1)>>1),T) : F2xq_mul(gel(V, i-1),x,T); } } return V; } GEN F2xq_matrix_pow(GEN y, long n, long m, GEN P) { return F2xV_to_F2m(F2xq_powers(y,m-1,P),n); } ulong F2xq_trace(GEN x, GEN T) { pari_sp av = avma; ulong t; GEN z = F2x_mul(x, F2x_deriv(T)); z = F2x_div(F2x_shift(z, 1), T); t = lgpol(z)?F2x_coeff(z,0):0; avma=av; return t; } GEN F2xq_conjvec(GEN x, GEN T) { long i, l = F2x_degree(T); GEN z = cgetg(l,t_COL); gel(z,1) = vecsmall_copy(x); for (i=2; i1) pari_warn(warnmem,"F2xq_sqrt (i = %ld)",i); a = gerepileuptoleaf(av, a); } } return gerepileuptoleaf(av, a); } GEN F2xq_sqrtn(GEN a, GEN n, GEN T, GEN *zeta) { if (!lgpol(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, trivfact()); 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=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 != lg(y[1])) break; z=cgetg(ly+1,t_MAT); gel(z,1) = x; for (i=2; i<=ly; i++) z[i]=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 != lg(c[1])) { if (h) err_cat(gel(y2,0), c); h = lg(c[1]); } L += nc; z = new_chunk(nc) - 1; for (i=1; i<=nc; i++) z[i] = c[i]; } z = new_chunk(1); *z = evaltyp(t_MAT) | evallg(L); return z; } /* see catmany() */ static GEN catmanySTR(GEN y1, GEN y2) { long i, L = 1; GEN z, y; char *s, *S = (char*)avma; pari_sp av = avma; (void)new_chunk(1); *--S = 0; for (y = y2; y >= y1; y--) { char *c = GSTR( gel(y,0) ); long nc = strlen(c); if (nc == 0) continue; L += nc; c += nc; (void)new_chunk(nchar2nlong(nc)); for (i=1; i<=nc; i++) *--S = *--c; } avma = av; z = cgetg(nchar2nlong(L) + 1, t_STR); s = GSTR(z); if (S != s) { for (i = 0; i <= L; i++) *s++ = *S++; } 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++) z[i] = 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 tx = typ(x), lx, t, i; GEN z; if (tx == t_VEC) lx = lg(x); else if (tx == t_LIST) { x = list_data(x); lx = x ? lg(x): 1; } else { pari_err(typeer,"concat"); return NULL; /* not reached */ } if (lx==1) pari_err(talker,"trying to concat elements of an empty vector"); 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)); } 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) return 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 && lg(x[1]) != lg(y[1])) 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 != lg(y[1])) 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 1) pari_err(talker, "discriminant not congruent to 0,1 mod 4 in %s", f); } void check_quaddisc_real(GEN x, long *r, const char *f) { long sx; check_quaddisc(x, &sx, r, f); if (sx < 0) pari_err(talker, "negative discriminant in %s", f); } void check_quaddisc_imag(GEN x, long *r, const char *f) { long sx; check_quaddisc(x, &sx, r, f); if (sx > 0) pari_err(talker, "positive discriminant in %s", f); } static GEN Zquadpoly(GEN x, long v) { long res, sx; GEN y, p1; check_quaddisc(x, &sx, &res, "quadpoly"); y = cgetg(5,t_POL); y[1] = evalsigne(1) | evalvarn(v); p1 = shifti(x,-2); togglesign(p1); /* p1 = - floor(x/4) [ = -x/4 or (1-x)/4 ] */ if (!res) gel(y,3) = gen_0; else { if (sx < 0) p1 = gerepileuptoint((pari_sp)y, addsi(1,p1)); gel(y,3) = gen_m1; } gel(y,2) = p1; gel(y,4) = gen_1; return y; } GEN quadpoly0(GEN x, long v) { if (is_matvec_t(typ(x))) { long i, l; GEN y = cgetg_copy(x, &l); for (i=1; i 0) swap(x, y); qfb_comp(z, x,y); if (raw) return gerepilecopy(av,z); return gerepileupto(av, redimag(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(typeer,"composition"); switch(tx) { case t_QFI: return qficompraw(x,y); case t_QFR: return qfrcompraw(x,y); } pari_err(typeer,"composition"); 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(typeer,"composition"); qfb_sqr(z,x); if (raw) return gerepilecopy(av,z); return gerepileupto(av, redimag(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(typeer,"composition"); 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) { long prec; if (typ(x) != t_QFR) pari_err(typeer,"qfr_1"); prec = precision(gel(x,4)); if (!prec) pari_err(talker,"not a t_REAL in 4th component of a t_QFR"); return qfr_1_by_disc(qfb_disc(x), prec); } 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; } static GEN qfi_1_by_disc(GEN D) { GEN y = cgetg(4,t_QFI); long r; check_quaddisc_imag(D, &r, "qfi_1_by_disc"); gel(y,1) = gen_1; gel(y,2) = r? gen_1: gen_0; /* upon return, y[3] = (1-D) / 4 or -D / 4, whichever is an integer */ gel(y,3) = shifti(D,-2); if (r) { pari_sp av = avma; gel(y,3) = gerepileuptoint(av, addis(gel(y,3),-1)); } /* at this point y[3] < 0 */ setsigne(y[3], 1); return y; } GEN qfi_1(GEN x) { if (typ(x) != t_QFI) pari_err(typeer,"qfi_1"); 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(talker,"not a t_QFR in qfrpowraw"); 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(talker,"not a t_QFI in qfipow"); 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, v1, v2, v3, Q; if (x==y) return nudupl(x,L); if (typ(x) != t_QFI || typ(y) != t_QFI) pari_err(talker,"not a t_QFI in nucomp"); 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,&v1); 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 gerepileupto(av, redimag(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(talker,"not a t_QFI in nudupl"); a = gel(x,1); b = gel(x,2); d1 = bezout(b,a, &u,&v); 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 gerepileupto(av, redimag(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, l; if (typ(n) != t_INT) pari_err(talker,"not an integer exponent in nupow"); if (gequal1(n)) return gcopy(x); av = avma; y = qfi_1(x); if (!signe(n)) return y; l = sqrti(shifti(sqrti(gel(y,3)),1)); y = gen_pow(x, n, (void*)l, &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 */ 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; } /* 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); *c = subii(*c, mulii(q, shifti(addii(*b, r),-1))); *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; } GEN redimag(GEN q) { GEN Q = cgetg(4, t_QFI); pari_sp av = avma, av2, lim = stack_lim(av, 1); GEN 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(lgefint(a) + lgefint(b) + lgefint(c) + 3); av2 = avma; 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; swap(a,c); b = negi(b); /* apply rho */ REDB(a,&b,&c); if (low_stack(lim, stack_lim(av, 1))) { if (DEBUGMEM>1) pari_warn(warnmem, "redimag"); gerepileall(av2, 3, &a,&b,&c); } } if (cmp == 0 && signe(b) < 0) b = negi(b); avma = av; gel(Q,1) = icopy(a); gel(Q,2) = icopy(b); gel(Q,3) = icopy(c); return 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(x[2]) < 0) setsigne(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) { long d = expo(x[5]) - (1L << EMAX); if (d >= 0) { gel(x,4) = addsi(1, gel(x,4)); setexpo(x[5], d); } } /* (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)); setexpo(u, expo(u+EMAX)); t = addrr(t, u); } setexpo(t, expo(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); if (u == gen_0) pari_err(talker, "reducible form in qfr_rho"); 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, y, b = gel(x,2), c = gel(x,3); rho_get_BC(&B, &C, b, c, S); y = cgetg(4, t_VEC); gel(y,1) = c; gel(y,2) = B; gel(y,3) = C; return y; } /* 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)))); setexpo(d, expo(d)-1); d0 = addrr(d0, d); } else if (!gequal1(d)) /* avoid loss of precision */ { d = logr_abs(d); setexpo(d, expo(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(arither1); if (!signe(S->D)) pari_err(talker,"reducible form in qfr_init"); } 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 = lg(d), l = nbits2prec(-expo(d)); if (l > prec) prec = l; if (prec < 3) prec = 3; 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(arither1); 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(arither1); 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(arither1); 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(talker,"not a real quadratic form in redreal"); 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(flagerr,"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(talker,"discriminant not congruent to 0,1 mod 4 in primeform"); if (p == 2) { switch(s) { case 0: b = 0; break; case 1: b = 1; break; case 4: b = 2; break; default: pari_err(sqrter5); b = 0; /* -Wall */ } c = shifti(subsi(s,x), -3); } else { b = Fl_sqrt(umodiu(x,p), p); if (b == ~0UL) pari_err(sqrter5); /* 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) { pari_sp av; long s, sx = signe(x), sp = signe(p); GEN y, b, absp; if (typ(x) != t_INT || !sx) pari_err(arither1); if (typ(p) != t_INT || !sp) pari_err(arither1); if (lgefint(p) == 3) { if (p[2] == 1) { if (sx < 0) { if (sp < 0) pari_err(impl,"negative definite t_QFI"); 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, p[2]); 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(talker,"discriminant not congruent to 0,1 mod 4 in primeform"); absp = absi(p); av = avma; b = Fp_sqrt(x, absp); if (!b) pari_err(sqrter5); 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 SL_2(Z), return (N*M^-1)[,1] * */ static GEN SL2_div_mul_e1(GEN N, GEN M) { GEN b = gcoeff(M, 2, 1); GEN d = gcoeff(M, 2, 2); GEN p2 = cgetg(3, t_VEC); gel(p2,1) = subii(mulii(gcoeff(N, 1, 1), d), mulii(gcoeff(N, 1, 2), b)); gel(p2,2) = subii(mulii(gcoeff(N, 2, 1), d), mulii(gcoeff(N, 2, 2), b)); return p2; } /* Let M and N in SL_2(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); GEN d = gcoeff(M, 2, 2); GEN p2 = cgetg(3, t_VEC); gel(p2,1) = addii(mulii(gcoeff(N, 1, 1), d), mulii(gcoeff(N, 1, 2), b)); gel(p2,2) = addii(mulii(gcoeff(N, 2, 1), d), mulii(gcoeff(N, 2, 2), b)); return p2; } /*Test equality modulo GL2*/ 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 (gequal1(a)) return qfbsolve_cornacchia(c, p, 0); if (gequal1(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) { pari_sp ltop = avma; GEN N; GEN V = gel(A,1); GEN M = gel(A,2); GEN a = gel(V,1); GEN b = gel(V,2); GEN c = gel(V,3); GEN d = qfb_disc3(a,b,c); GEN rd = sqrti(d); 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) q = negi(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) { pari_sp ltop = avma, btop, st_lim; GEN u1, u2, v1, v2; GEN M; GEN a = gel(V,1); GEN b = gel(V,2); GEN c = gel(V,3); GEN d = qfb_disc3(a,b,c); GEN rd = sqrti(d); btop = avma; st_lim = stack_lim(btop, 1); 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(btop, 1))) { if (DEBUGMEM>1) pari_warn(warnmem,"redrealsl2"); gerepileall(btop, 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, d = qfb_disc(Q); if (kronecker(d, p) < 0) { avma = ltop; return gen_0; } M = N = redrealsl2(Q); P = primeform(d, p, DEFAULTPREC); P1 = redrealsl2(P); togglesign( gel(P,2) ); P2 = redrealsl2(P); btop = avma; st_lim = stack_lim(btop, 1); while (!ZV_equal(gel(M,1), gel(P1,1)) && !ZV_equal(gel(M,1), gel(P2,1))) { M = redrealsl2step(M); 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); } N = ZV_equal(gel(M,1),gel(P1,1))? gel(P1,2): gel(P2,2); return gerepilecopy(ltop, SL2_div_mul_e1(gel(M,2),N)); } GEN qfbsolve(GEN Q,GEN n) { if (typ(n)!=t_INT) pari_err(typeer,"qfbsolve"); switch(typ(Q)) { case t_QFI: return qfisolvep(Q,n); case t_QFR: return qfrsolvep(Q,n); default: pari_err(typeer,"qfbsolve"); 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 || typ(p) != t_INT) pari_err(typeer, "cornacchia"); if (signe(d) <= 0) pari_err(talker, "d must be positive"); *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 || typ(p) != t_INT) pari_err(typeer, "cornacchia"); if (signe(d) <= 0) pari_err(talker, "d must be positive"); *px = *py = gen_0; k = mod4(d); if (k == 1 || k == 2) pari_err(talker,"d must be 0 or 3 mod 4"); 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.5.5/src/basemath/Hensel.c0000644000175000017500000004110112147140046015035 0ustar billbill/* $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. */ #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++) { V[i] = 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(talker, "relatively prime polynomials expected"); 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; 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, RgX_mul(a,b)); 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 = RgX_add(RgX_mul(u,g), RgX_mul(t,b)); 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 = RgX_add(RgX_mul(u,a2), RgX_mul(v,b2)); 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 = RgX_add(RgX_mul(u,g), RgX_mul(t,b)); 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 || e0 < 1) pari_err(talker, "MultiLift: bad args"); if (e0 == 1) return a; if (DEBUGLEVEL > 3) timer_start(&Ti); if (typ(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(talker, "not a polynomial in polhensellift"); RgX_check_ZXY(pol, "polhensellift"); t = typ(L); if (!is_vec_t(t) || lg(L) < 3) pari_err(talker, "not a factorization in polhensellift"); t = typ(p); if (t == t_VEC) /* [p, T] */ { T = gel(p,2); if (typ(T) != t_POL) pari_err(talker, "incorrect T in polhensellift"); RgX_check_ZX(T, "polhensellift"); p = gel(p,1); t = typ(p); } if (t != t_INT) pari_err(talker, "incorrect p in polhensellift"); if (N < 1) pari_err(talker, "not a positive exponent in polhensellift"); 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_ZXY(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(GEN f, GEN a, GEN T, GEN p, long e) { pari_sp av = avma; GEN q = p, fr, W; ulong mask; a = Fq_red(a, T, q); if (e == 1) return a; mask = quadratic_prec_mask(e); fr = FpXQX_red(f, T, q); W = Fq_inv(FqX_eval(RgX_deriv(fr), a, T, q), T, q); /* 1/f'(a) mod (T,p) */ for(;;) { q = sqri(q); if (mask & 1) q = diviiexact(q, p); mask >>= 1; fr = FpXQX_red(f,T,q); a = Fq_sub(a, Fq_mul(W, FqX_eval(fr, a, T,q), T,q), T,q); if (mask == 1) return gerepileupto(av, a); W = Fq_sub(gmul2n(W,1), Fq_mul(Fq_sqr(W,T,q), FqX_eval(RgX_deriv(fr),a,T,q), T, q), T,q); } } /* 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); } /* Same as ZpXQX_liftroot for the polynomial X^n-b */ GEN ZpXQ_sqrtnlift(GEN b, GEN n, GEN a, GEN T, GEN p, long e) { pari_sp av = avma; GEN q = p, n_1, w; ulong mask; a = Fq_red(a, T, q); if (e == 1) return a; n_1 = subis(n,1); mask = quadratic_prec_mask(e); w = Fq_inv(Fq_mul(n, Fq_pow(a, n_1, T,q), T,q), T,q); for(;;) { q = sqri(q); if (mask & 1) q = diviiexact(q, p); mask >>= 1; /* a -= w (a^n - b) */ a = Fq_sub(a, Fq_mul(w, Fq_sub(Fq_pow(a, n, T,q), b, T,q), T,q), T,q); if (mask == 1) return gerepileupto(av, a); /* w += w - w^2 n a^(n-1)*/ w = Fq_sub(gmul2n(w,1), Fq_mul(Fq_sqr(w,T,q), Fq_mul(n, Fq_pow(a,n_1,T, q), T,q), T,q), T,q); } } pari-2.5.5/src/basemath/buch4.c0000644000175000017500000005660212147140046014640 0ustar billbill/* $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. */ /*******************************************************************/ /* */ /* S-CLASS GROUP AND NORM SYMBOLS */ /* (Denis Simon, desimon@math.u-bordeaux.fr) */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" /* p > 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 || typ(p)!=t_INT) pari_err(typeer,"zpsoluble"); 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(bugparier,"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 = int_elt_val(nf, x, p, pr_get_tau(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 long psquare2nf(GEN nf,GEN x,GEN pr,GEN zinit) { long v; pari_sp av = avma; x = nf_to_scalar_or_basis(nf, x); /* x /= pi^v, pi a pr-uniformizer. v >= 0 */ if (typ(x) == t_INT) { if (!signe(x)) return 1; v = Z_lvalrem(x, 2, &x) * pr_get_e(pr); } else v = int_elt_val(nf, x, pr_get_p(pr), pr_get_tau(pr), &x); if (v&1) return 0; /* now (x,pr) = 1 */ v = check2(nf,x,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 = int_elt_val(nf, gx, pr_get_p(pr), pr_get_tau(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) || gequal0(b)) pari_err (talker,"0 argument in nfhilbertp"); 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 (typ(S) != t_VEC) pari_err(typeer,"bnfsunit"); 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 && lg(dep[1]) > 1) pari_err(bugparier,"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(typeer,"bnfissunit"); 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(flagerr, "rnfisnorminit"); T = get_bnfpol(T, &bnf, &nf); vbas = varn(T); 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 (varncmp(varn(relpol), vbas) >= 0) pari_err(talker,"main variable must be of higher priority in rnfisnorminit"); if (drel <= 2) galois = 1; rnfeq = NULL; /* no reltoabs needed */ if (nf_get_degree(nf) == 1) { /* over Q */ polabs = simplify_shallow(lift(relpol)); k = gen_0; } else if (galois == 2) { /* needs reltoabs */ rnfeq = rnfequation2(bnf, relpol); polabs = gel(rnfeq,1); gel(rnfeq,2) = lift_intern(gel(rnfeq,2)); k = gel(rnfeq,3); } else { long sk; polabs = rnfequationall(bnf, relpol, &sk, NULL); k = stoi(sk); } 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 = rnfeq? pol_up(rnfeq, relpol, vbas): relpol; galois = nfissplit(gsubst(nfabs, nf_get_varn(nfabs), pol_x(vbas)), 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, theta, 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(talker,"please apply rnfisnorminit first"); bnf = gel(T,1); rel = gel(T,2); relpol = gel(T,3); theta = 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) { byteptr d = diffptr; long p = 0; maxprime_check((ulong)flag); for(;;) { NEXT_PRIME_VIADIFF(p, d); if (p > flag) break; pr_append(nf,rel, utoipos(p),&prod,&S1,&S2); } } else if (flag < 0) fa_pr_append(nf,rel,stoi(-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,3); sunitrel = shallowconcat(futu, gel(bnfsunit(rel,S2,3), 1)); A = lift_intern(bnfissunit(bnf,bnfS,x)); L = lg(sunitrel); itu = lg(nf[6])-1; /* index of torsion unit in bnfsunit(nf) output */ M = cgetg(L+1,t_MAT); for (i=1; i 1 and 0 < i < lg(x[1]) */ static GEN ZMrow_ZC_mul_i(GEN x, GEN y, long lx, long i) { 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 c; } static ulong Flmrow_Flc_mul_SMALL(GEN x, GEN y, ulong p, long lx, long i) { ulong c = ucoeff(x,i,1) * y[1]; long k; for (k = 2; k < lx; k++) { c += ucoeff(x,i,k) * y[k]; if (c & HIGHBIT) c %= p; } return c % p; } static ulong Flmrow_Flc_mul(GEN x, GEN y, ulong p, long lx, long i) { ulong c = Fl_mul(ucoeff(x,i,1), y[1], p); long k; for (k = 2; k < lx; k++) c = Fl_add(c, Fl_mul(ucoeff(x,i,k), y[k], p), p); return c; } static GEN Flm_Flc_mul_i_2(GEN x, GEN y, long lx, long l) { long i,j; GEN z = NULL; for (j=1; j2) p = icopy(p); for (i=2; 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)bit_accuracy_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(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; byteptr primepointer; /* allow computing the primes following p */ }; 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 = gdiv(RgX_div_by_X_x(T, gel(L,i), NULL), gel(prep,i)); gel(M,i) = RgX_to_RgV(P,n); } return gerepileupto(ltop, gmul(den, M)); } /* 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) { long r1,r2; nf_get_sign(nf, &r1, &r2); if (!r2) L = r; else { long i,j, N = r1+2*r2; L = cgetg(N + 1, t_VEC); for (i = 1; i <= r1; i++) gel(L,i) = gel(r,i); for (j = i; j <= N; i++) { gel(L,j++) = gel(r,i); gel(L,j++) = gconj(gel(r,i)); } } } else L = cleanroots(T, prec); if (DEBUGLEVEL>=4) timer_printf(&ti,"roots"); prep = vandermondeinverseprep(L); if (!dn) { GEN dis, res = divide_conquer_prod(gabs(prep,prec), mpmul); dbg_block(); dis = ZX_disc_all(T, 1+logint(res,gen_2,NULL)); dbg_release(); den = indexpartial(T,dis); if (ptdis) *ptdis = dis; } else { if (typ(dn) != t_INT || signe(dn) <= 0) pari_err(talker, "incorrect denominator in initgaloisborne: %Ps", 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 = 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 = addsr(1, gmul(borne,gmulsg(d, powru(borneroots, d)))); borneroots = addsr(1, gmul(borne, borneroots)); av2 = avma; /*We use d-1 test, so we must overlift to 2^BITS_IN_LONG*/ gb->valsol = logint(gmul2n(borneroots,2+BITS_IN_LONG), gb->l,NULL); gb->valabs = logint(gmul2n(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, ceil_safe(shiftr(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(gmul2n(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(Q),1); 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) { long v = varn(gl->T); 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); gt->pauto = cgetg(gt->f + 1, t_VEC); gel(gt->pauto,1) = pol_x(v); gel(gt->pauto,2) = gcopy(plift); if (gt->f > 2) { pari_sp av = avma, ltop; long i, nautpow = brent_kung_optpow(gt->n-1,gt->f-2); GEN autpow; pari_timer ti; if (DEBUGLEVEL >= 1) timer_start(&ti); autpow = FpXQ_powers(plift,nautpow,gl->TQ,gl->Q); ltop = avma; for (i = 3; i <= gt->f; i++) gel(gt->pauto,i) = FpX_FpXQV_eval(gel(gt->pauto,i-1),autpow,gl->TQ,gl->Q); /*Somewhat paranoid with memory, but this function use a lot of stack.*/ gerepilecoeffssp(av, ltop, gt->pauto + 3, gt->f-2); if (DEBUGLEVEL >= 1) 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; } cache[j] = cache[j+1]+mael(Cd,h,j); } if (headlongisint(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 = const_vecsmall(n, 0); 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) { long Z = mael(PW,1,pf[1]); for (j = 2; j <= n; j++) Z += mael(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 V, 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(F[1])-1; c = lg(B)-1; d = lg(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 */ { 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 += mael(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 += mael(W,mael(G,p6,p3),mael(G,p1,p2)); p3 -= s; if (p3 <= 0) p3 += b; } ar[p1] = ar[p1+1] + V; } if (!headlongisint(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(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 = lg(NS[1]); 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(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(talker,"p too small in fixedfieldsympol"); 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(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++) S[ Oi[j] ] = 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; byteptr primepointer, pp; pari_timer ti; if (DEBUGLEVEL >= 1) timer_start(&ti); n = degpol(T); O = const_vecsmall(n, 0); 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); pp = primepointer = diffptr; p = init_primepointer(n*maxss(expu(n)-3, 2), 0, &primepointer); 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 */ if (nbtest++) { avma = av; NEXT_PRIME_VIADIFF_CHECK(p,primepointer); } 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; pp = primepointer; /* 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 = avma; p = init_primepointer(linf+1, p, &primepointer); for(;; avma = av2) /*find a totally split prime l*/ { 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; } NEXT_PRIME_VIADIFF_CHECK(p,primepointer); } } ga->group = (enum ga_code)group; ga->deg = deg; ga->ord = order; ga->primepointer = pp; 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++) coeff(MT,i,j) = coeff(MT,j,i) = coeff(mt,i,j)+coeff(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); ar[4] = mael(MT,11,12); ar[3] = ar[4] + mael(MT,9,10); ar[2] = ar[3] + mael(MT,7,8); ar[1] = ar[2] + mael(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]); ar[1] = ar[2] + mael(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]); ar[2] = ar[3] + mael(MT,t[6],t[7]); ar[1] = ar[2] + mael(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]); ar[3] = ar[4] + mael(MT,t[8],t[9]); ar[2] = ar[3] + mael(MT,t[6],t[7]); ar[1] = ar[2] + mael(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]); ar[4] = mael(MT,t[10],t[11]); ar[3] = ar[4] + mael(MT,t[8],t[9]); ar[2] = ar[3] + mael(MT,t[6],t[7]); ar[1] = ar[2] + mael(MT,t[4],t[5]); } } g = ar[1]+mael(MT,t[0],t[1])+mael(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++) { long 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++) { long 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(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(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 = const_vecsmall(6, 0); 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) = const_vecsmall(gt.g, 0); gel(gt.Cd,i) = const_vecsmall(gt.g, 0); } 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; } dbg_block(); lo = listznstarelts(dg, n / gf->fp); dbg_release(); 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(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; long Try = 0, n = degpol(T), deg, gmask = (ga->group&ga_ext_2)? 3: 1; byteptr primepointer = ga->primepointer; GEN frob, Lden = makeLden(L,den,gb); deg = gf->deg = ga->deg; gf->p = ga->p; for (;;) { pari_sp lbot, av = avma; GEN Ti, Tp = ZX_to_Flx(T, gf->p); long nb, d; if (!Flx_is_squarefree(Tp, gf->p)) goto nextp; Ti = gel(FpX_factor(Flx_to_ZX(Tp), utoipos(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))) goto nextp; if (DEBUGLEVEL >= 1) err_printf("GaloisConj: Trying p=%ld\n", gf->p); 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 almost certainly not weakly super solvable"); return NULL; } nextp: NEXT_PRIME_VIADIFF_CHECK(gf->p, primepointer); avma = av; } } 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 Pg) { pari_sp ltop=avma; GEN P, PL, Pden, PM, Pp; GEN tau, PG; long g,gp; long x=varn(Tp); P=gel(V,3); PL=gel(V,2); gp=lg(Pmod)-1; 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); tau = RgX_to_FpX(tau, ip); tau = FpX_FpXQ_eval(gel(Pmod,gp), tau,Pp,ip); tau = FpX_gcd(Pp, tau,ip); tau = FpX_normalize(tau, ip); for (g = 1; g <= gp; g++) if (ZX_equal(tau, gel(Pmod,g))) break; if (g == lg(Pmod)) return NULL; Pg[1]=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); mod = Pgb.ladicabs; mod2 = shifti(mod, -1); if (PG == gen_0) return NULL; for (j = 1; j < lg(PG[1]); j++) { pari_sp btop=avma; tau = permtopol(gmael(PG,1,j), PL, PM, Pden, mod, mod2, x); tau = RgX_to_FpX(tau, ip); tau = FpX_FpXQ_eval(gel(Pmod,gp), tau,Pp,ip); tau = FpX_gcd(Pp, tau,ip); tau = FpX_normalize(tau, ip); for (g = 1; g < lg(Pmod); g++) if (ZX_equal(tau, gel(Pmod,g))) break; if (g == lg(Pmod)) return NULL; avma=btop; Pg[j]=g; } } return gerepilecopy(ltop,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 galoisgen(GEN T, GEN L, GEN M, GEN den, struct galois_borne *gb, const struct galois_analysis *ga) { struct galois_test td; struct galois_frobenius gf; pari_sp lbot, ltop2, ltop = avma; long p, deg, x, i, j, n = degpol(T); GEN sigma, Tmod, res, res1, res2, pf, ip, frob, O, PG, PG1, PG2, Pg; if (!ga->deg) 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); lbot = avma; PG = a4galoisgen(&td); freetest(&td); if (PG != gen_0) return gerepile(ltop, lbot, 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"); lbot = avma; initlift(T, den, stoi(ga->p4), L, makeLden(L,den,gb), gb, &gl); PG = s4galoisgen(&gl); if (PG != gen_0) return gerepile(ltop, lbot, 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(O[1])-1; sigma = permtopol(frob, L, M, den, gb->ladicabs, shifti(gb->ladicabs,-1), x); if (DEBUGLEVEL >= 9) err_printf("GaloisConj:Orbite:%Ps\n", O); if (deg == n) /* cyclic */ { lbot = avma; res = cgetg(3, t_VEC); gel(res,1) = mkvec( cyc_pow_perm(O,1) ); gel(res,2) = mkvecsmall(deg); return gerepile(ltop, lbot, res); } if (DEBUGLEVEL >= 9) err_printf("GaloisConj:Frobenius:%Ps\n", sigma); Pg=cgetg(lg(O),t_VECSMALL); { 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, Pg); if (PG == NULL) { avma = ltop; return gen_0; } if (DEBUGLEVEL >= 4) err_printf("GaloisConj:Back to Earth:%Ps\n", PG); PG=gerepileupto(btop, PG); } inittest(L, M, gb->bornesol, gb->ladicsol, &td); PG1 = gel(PG, 1); PG2 = gel(PG, 2); lbot = avma; res = cgetg(3, t_VEC); gel(res,1) = res1 = cgetg(lg(PG1) + 1, t_VEC); gel(res,2) = res2 = cgetg(lg(PG1) + 1, t_VECSMALL); gel(res1, 1) = cyc_pow_perm(O,1); res2[1] = deg; for (i = 2; i < lg(res1); i++) gel(res1,i) = cgetg(n+1, t_VECSMALL); ltop2 = avma; for (j = 1; j < lg(PG1); j++) { long sr, k; GEN X = cgetg(lg(O), t_VECSMALL); GEN oX = cgetg(lg(O), t_VECSMALL); GEN gj = gel(PG1, j); long s = gf.psi[Pg[j]]; GEN B = perm_cycles(gj); long oj = lg(B[1]) - 1; GEN F = factoru(oj); GEN Fp = gel(F,1); GEN Fe = gel(F,2); if (DEBUGLEVEL >= 6) err_printf("GaloisConj: G[%d]=%Ps of relative order %d\n", j, gj, oj); B = perm_cycles(gel(PG1,j)); pf = identity_perm(n); 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); 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); 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) { freetest(&td); avma = ltop; return gen_0; } for (i=1; i= 4) err_printf("GaloisConj:Fini!\n"); freetest(&td); return gerepile(ltop, lbot, res); } /* 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 = degpol(T); if (nf) { if (!den) den = Q_denom(nf_get_zk(nf)); } else { if (n <= 0) pari_err(constpoler, "galoisinit"); RgX_check_ZX(T, "galoisinit"); if (!ZX_is_squarefree(T)) pari_err(talker, "Polynomial not squarefree in galoisinit"); if (!gequal1(gel(T,n+2))) pari_err(talker, "non-monic polynomial in galoisinit"); } 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(talker, "Second arg. must be integer in galoisconj4"); 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 p, c, nbtest = 0, n = degpol(T), nbmax = (n < 10)? 20: (n<<1) + 1; byteptr diff = diffptr; #if 0 c = sturm(T); c = ugcd(c, n - c); /* too costly: finite primes are cheaper */ #else c = n; #endif p = init_primepointer(pinit, 0, &diff); for (; nbtest < nbmax && c > 1; avma = av) { GEN L, Tp = ZX_to_Flx(T,p); long i, nb; if (Flx_is_squarefree(Tp, p)) { /* 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 (DEBUGLEVEL >= 6) err_printf("NumberOfConjugates [%ld]:c=%ld,p=%ld\n", nbtest,c,p); } NEXT_PRIME_VIADIFF_CHECK(p,diff); } 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(flagerr, "nfgaloisconj"); return NULL; /*not reached*/ } /******************************************************************************/ /* Isomorphism between number fields */ /******************************************************************************/ long isomborne(GEN P, GEN den, GEN p) { pari_sp av = avma; struct galois_borne gb; gb.l = p; (void)galoisborne(P,den,&gb,degpol(P)); avma = av; return gb.valsol; } /******************************************************************************/ /* Galois theory related algorithms */ /******************************************************************************/ GEN checkgal(GEN gal) { if (typ(gal) == t_POL) pari_err(talker, "please apply galoisinit first"); if (typ(gal) != t_VEC || lg(gal) != 9) pari_err(talker, "Not a Galois group in a Galois related function"); 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(typeer, "galoispermtopol"); 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 = const_vecsmall(lg(perm)-1, 0); 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++) V[k] = mael(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(typeer, "galoisfixedfield"); } static int is_group(GEN g) { return typ(g)==t_VEC && lg(g)==3 && typ(g[1])==t_VEC && typ(g[2])==t_VECSMALL; } GEN galoisfixedfield(GEN gal, GEN perm, long flag, long y) { pari_sp lbot, ltop = avma; GEN T, L, P, S, PL, O, res, mod, mod2; long x, n, i; if (flag<0 || flag>2) pari_err(flagerr, "galoisfixedfield"); gal = checkgal(gal); T = gal_get_pol(gal); x = 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, x); 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, x); if (flag==0) { lbot = avma; 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 (y <= x) pari_err(talker,"variable priority too high in galoisfixedfield"); lbot = avma; res = cgetg(4, t_VEC); gel(res,3) = fixedfieldfactor(L,O,gal_get_group(gal), PM,Pden,mod,mod2,x,y); } gel(res,1) = gcopy(P); gel(res,2) = gmodulo(S, T); return gerepile(ltop, lbot, 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(flagerr,"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.5.5/src/basemath/FpE.c0000644000175000017500000002431212147140046014276 0ustar billbill/* $Id$ 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 */ /***********************************************************************/ /** **/ /** 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 FpE_dbl(GEN P, GEN a4, GEN p) { pari_sp ltop = avma; GEN lambda, C, D, x = gel(P,1), y = gel(P,2); if (ell_is_inf(P) || !signe(y)) return ellinf(); lambda = Fp_div(Fp_add(Fp_mulu(Fp_sqr(x,p), 3, p), a4, p), Fp_mulu(y, 2, p), p); C = Fp_sub(Fp_sqr(lambda, p), Fp_mulu(x, 2, p), p); D = Fp_sub(Fp_mul(lambda, Fp_sub(x, C, p), p), y, p); return gerepilecopy(ltop, mkvec2(C,D)); } static GEN FpE_add_i(GEN P, GEN Q, GEN a4, GEN p) { GEN Px = gel(P,1), Py = gel(P,2); GEN Qx = gel(Q,1), Qy = gel(Q,2), lambda, C, D; if (ell_is_inf(P)) return Q; if (ell_is_inf(Q)) return P; if (equalii(Px, Qx)) { if (equalii(Py, Qy)) return FpE_dbl(P, a4, p); else return mkvec(gen_0); } lambda = Fp_div(Fp_sub(Py, Qy, p), Fp_sub(Px, Qx, p), p); C = Fp_sub(Fp_sub(Fp_sqr(lambda, p), Px, p), Qx, p); D = Fp_sub(Fp_mul(lambda, Fp_sub(Px, C, p), p), Py, p); return mkvec2(C,D); } GEN FpE_add(GEN P, GEN Q, GEN a4, GEN p) { pari_sp av = avma; return gerepilecopy(av, FpE_add_i(P,Q,a4,p)); } 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 z = FpE_add_i(P, FpE_neg_i(Q, p), a4, p); return gerepilecopy(av, z); } struct _FpE { GEN a4; 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 point on E */ GEN random_FpE(GEN a4, GEN a6, GEN p) { pari_sp ltop = avma; GEN x, y, rhs; do { avma= ltop; x = randomi(p); /* x^3+a4*x+a6 = x*(x^2+a4)+a6 */ rhs = Fp_add(Fp_mul(x, Fp_add(Fp_sqr(x, p), a4, p), p), a6, p); } while (kronecker(rhs, p) < 0); y = Fp_sqrt(rhs, p); if (!y) pari_err(talker,"not a prime number"); return gerepilecopy(ltop, mkvec2(x, y)); } static int FpE_cmp(GEN x, GEN y) { if (ell_is_inf(x)) return !ell_is_inf(y); if (ell_is_inf(y)) return -1; return lexcmp(x,y); } static const struct bb_group FpE_group={_FpE_add,_FpE_mul,NULL,NULL,FpE_cmp,ell_is_inf}; 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_eltorder(z, o, (void*)&e, &FpE_group)); } /***********************************************************************/ /** **/ /** Pairings **/ /** **/ /***********************************************************************/ /* Formulae from a GP script by J.E.Cremona */ static GEN FpE_ffvert(GEN t, GEN pt, GEN p) { return ell_is_inf(t)?gen_1:Fp_sub(gel(pt, 1), gel(t, 1), p); } static GEN FpE_fftang(GEN t, GEN pt, GEN a4, GEN p) { GEN dyf, dxf; if (ell_is_inf(t)) return gen_1; if (signe(gel(t, 2))==0) return Fp_sub(gel(pt, 1), gel(t, 1), p); dxf = Fp_neg(Fp_add(Fp_mulu(Fp_sqr(gel(t, 1), p), 3, p), a4, p), p); dyf = Fp_mulu(gel(t, 2), 2, p); return Fp_add(Fp_sub(gel(pt, 2), gel(t, 2), p), Fp_mul(Fp_div(dxf, dyf, p), Fp_sub(gel(pt, 1), gel(t, 1), p), p), p); } static GEN FpE_ffchord(GEN t, GEN s, GEN pt, GEN a4, GEN p) { if (ell_is_inf(s)) return FpE_ffvert(t, pt, p); if (ell_is_inf(t)) return FpE_ffvert(s, pt, p); if (equalii(gel(s, 1), gel(t, 1))) { if (equalii(gel(s, 2), gel(t, 2))) return FpE_fftang(t, pt, a4, p); else return FpE_ffvert(t, pt, p); } return Fp_sub(Fp_sub(gel(pt, 2), gel(t, 2),p), Fp_mul(Fp_div(Fp_sub(gel(t, 2), gel(s, 2), p), Fp_sub(gel(t, 1), gel(s, 1),p), p), Fp_sub(gel(pt, 1), gel(t, 1), p), p), p); } struct FpE_ff { GEN pt1, pt2, a4, p; }; static GEN FpE_ffadd(GEN S, GEN T, GEN pt1, GEN pt2, GEN a4, GEN p) { GEN s=gel(S,1), t=gel(T,1); GEN a, b, h; GEN ST = cgetg(3, t_VEC); GEN st = FpE_add(s, t, a4, p); pari_sp av=avma; gel(ST, 1) = st; a = Fp_mul(FpE_ffchord(s, t, pt1, a4, p), FpE_ffvert(st, pt2, p), p); if (signe(a)==0) return gen_0; b = Fp_mul(FpE_ffchord(s, t, pt2, a4, p), FpE_ffvert(st, pt1, p), p); if (signe(b)==0) return gen_0; h = Fp_mul(Fp_mul(gel(S,2), gel(T,2), p), Fp_div(a, b, p), p); gel(ST, 2) = gerepileupto(av, h); return ST; } static GEN _FpE_ffadd(void *data, GEN s, GEN t) { struct FpE_ff* ff=(struct FpE_ff*) data; if (s==gen_0 || t==gen_0) return gen_0; return FpE_ffadd(s,t,ff->pt1,ff->pt2,ff->a4,ff->p); } static GEN FpE_ffdbl(GEN S, GEN pt1, GEN pt2, GEN a4, GEN p) { GEN s=gel(S,1); GEN a, b, h; GEN S2 = cgetg(3, t_VEC); GEN s2 = FpE_dbl(s, a4, p); pari_sp av=avma; gel(S2, 1) = s2; a = Fp_mul(FpE_fftang(s, pt1, a4, p), FpE_ffvert(s2, pt2, p), p); if (signe(a)==0) return gen_0; b = Fp_mul(FpE_fftang(s, pt2, a4, p), FpE_ffvert(s2, pt1, p), p); if (signe(b)==0) return gen_0; h = Fp_mul(Fp_sqr(gel(S, 2), p), Fp_div(a, b, p), p); gel(S2, 2) = gerepileupto(av, h); return S2; } static GEN _FpE_ffdbl(void *data, GEN s) { struct FpE_ff* ff=(struct FpE_ff*) data; if (s==gen_0) return gen_0; return FpE_ffdbl(s,ff->pt1,ff->pt2,ff->a4,ff->p); } static GEN FpE_ffmul(GEN t, GEN m, GEN pt1, GEN pt2, GEN a4, GEN p) { struct FpE_ff ff; ff.pt1=pt1; ff.pt2=pt2; ff.a4=a4; ff.p=p; return gen_pow(t, m, (void*)&ff, _FpE_ffdbl, _FpE_ffadd); } static GEN FpE_ffmul1(GEN t, GEN m, GEN pt1, GEN pt2, GEN a4, GEN p) { return gel(FpE_ffmul(mkvec2(t, gen_1), m, pt1, pt2, a4, p), 2); } static GEN FpE_get_a6(GEN P, GEN a4, GEN p) { GEN x=gel(P,1), y=gel(P,2); GEN RHS = Fp_mul(x, Fp_add(Fp_sqr(x, p), a4, p), p); return Fp_sub(Fp_sqr(y, p), RHS, p); } static GEN FpE_weilpairing2(GEN t, GEN s, GEN p) { return gequal(s, t)? gen_1: subis(p, 1); } static GEN FpE_weilpairing3(GEN t, GEN s, GEN a4, GEN p) { pari_sp ltop = avma; GEN t2, s2, a, b; if (gequal(s, t)) return gen_1; t2 = FpE_dbl(t, a4, p); if (gequal(s, t2)) return gen_1; s2 = FpE_dbl(s, a4, p); a = Fp_mul(FpE_fftang(s, t, a4, p), FpE_fftang(t, s2, a4 ,p), p); b = Fp_mul(FpE_fftang(s, t2, a4, p), FpE_fftang(t, s, a4, p), p); return gerepileuptoint(ltop, Fp_sqr(Fp_div(a, b, p), p)); } static GEN FpE_weilpairing4(GEN t, GEN s, GEN m, GEN a4, GEN p) { pari_sp ltop = avma; GEN s2, t2, t3; GEN w; if (gequal(s, t)) return gen_1; s2 = FpE_dbl(s, a4, p); t2 = FpE_dbl(t, a4, p); if (ell_is_inf(s2)) return FpE_weilpairing2(s, t2, p); if (ell_is_inf(t2)) return FpE_weilpairing2(s2, t, p); if (gequal(s2, t2)) return FpE_weilpairing2(s2, FpE_sub(s, t, a4, p), p); t3 = FpE_add(t2, t, a4, p); if (gequal(s, t3)) return gen_1; w = Fp_mul(Fp_mul(FpE_ffmul1(s, m, t, t2, a4, p), FpE_ffmul1(s2,m, t2, t, a4, p), p), Fp_mul(FpE_ffmul1(t, m, s2, s, a4, p), FpE_ffmul1(t2,m, s, s2, a4, p), p), p); return gerepileuptoint(ltop, w); } GEN FpE_weilpairing(GEN t, GEN s, GEN m, GEN a4, GEN p) { pari_sp ltop=avma, av; GEN w, a6; if (ell_is_inf(s) || ell_is_inf(t)) return gen_1; switch(itou_or_0(m)) { case 2: return FpE_weilpairing2(s, t, p); case 3: return FpE_weilpairing3(s, t, a4, p); case 4: return FpE_weilpairing4(s, t, m, a4, p); } a6 = FpE_get_a6(t, a4, p); av = avma; while(1) { GEN r, rs, tr, a, b; avma = av; r = random_FpE(a4, a6, p); rs = FpE_add(r, s, a4, p); tr = FpE_sub(t, r, a4, p); if (ell_is_inf(rs) || ell_is_inf(tr) || ell_is_inf(r) || gequal(rs, t)) continue; a = FpE_ffmul(mkvec2(t, gen_1), m, rs, r, a4, p); if (a==gen_0) continue; b = FpE_ffmul(mkvec2(s, gen_1), m, tr, FpE_neg_i(r, p), a4, p); if (b==gen_0) continue; w = Fp_div(gel(a, 2), gel(b, 2), p); return gerepileuptoint(ltop, w); } } GEN FpE_tatepairing(GEN t, GEN s, GEN m, GEN a4, GEN p) { pari_sp ltop=avma, av; GEN w, a6; if (ell_is_inf(s) || ell_is_inf(t)) return gen_1; a6 = FpE_get_a6(t, a4, p); av = avma; while(1) { GEN r, rs, tr, a; avma = av; r = random_FpE(a4, a6, p); rs = FpE_add(r, s, a4, p); tr = FpE_sub(t, r, a4, p); if (ell_is_inf(rs) || ell_is_inf(tr) || ell_is_inf(r) || gequal(rs, t)) continue; a = FpE_ffmul(mkvec2(t, gen_1), m, rs, r, a4, p); if (a==gen_0) continue; w = Fp_pow(gel(a, 2), diviiexact(subis(p,1), m), p); return gerepileuptoint(ltop, w); } } pari-2.5.5/src/basemath/elliptic.c0000644000175000017500000036125512167755161015457 0ustar billbill/* $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. */ /********************************************************************/ /** **/ /** ELLIPTIC CURVES **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" void checkellpt(GEN z) { if (typ(z)!=t_VEC || lg(z) > 3) pari_err(talker, "not a point in ellxxx"); } void checkell5(GEN e) { if (typ(e)!=t_VEC || lg(e) < 6) pari_err(talker, "not an elliptic curve (ell5) in ellxxx"); } void checksmallell(GEN e) { if (typ(e)!=t_VEC || lg(e) < 14) pari_err(talker, "not an elliptic curve (smallell) in ellxxx"); } void checkell(GEN e) { if (typ(e)!=t_VEC || lg(e) < 20) pari_err(talker, "not an elliptic curve (ell) in ellxxx"); } static void checksmallell_real(GEN e) { checksmallell(e); switch (typ(ell_get_disc(e))) { case t_INT: case t_FRAC: break; default: pari_err(talker, "not an elliptic curve (smallell) over R in ellxxx"); } } void checkell_real(GEN e) { if (typ(e)!=t_VEC || !ell_is_real(e)) pari_err(talker, "not an elliptic curve over R in ellxxx"); } void checkell_padic(GEN e) { if (typ(e)!=t_VEC || !ell_is_real(e)) pari_err(talker, "not an elliptic curve over R in ellxxx"); } static void checkch(GEN z) { if (typ(z)!=t_VEC || lg(z) != 5) pari_err(talker,"not a coordinate change in ellxxx"); } /* 4 X^3 + b2 X^2 + 2b4 X + b6 */ static GEN RHSpol(GEN e) { GEN z = cgetg(6, t_POL); z[1] = evalsigne(1); gel(z,2) = ell_get_b6(e); gel(z,3) = gmul2n(ell_get_b4(e),1); gel(z,4) = ell_get_b2(e); gel(z,5) = utoipos(4); return z; } static int invcmp(void *E, GEN x, GEN y) { (void)E; return -gcmp(x,y); } INLINE GEN ell_realroot(GEN e) { return gmael(e,14,1); } static GEN ell_realrootprec(GEN e, long prec) { GEN R; if (lg(e)>14 && lg(ell_realroot(e))>=prec) return ell_realroot(e); R = cleanroots(RHSpol(e), prec); /* sort roots in decreasing order */ if (gsigne(ell_get_disc(e)) > 0) gen_sort_inplace(R, NULL, &invcmp, NULL); return gel(R,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)); } static GEN ell_to_small(GEN E) { return (lg(E) <= 14)? E: vecslice(E, 1, 13); } /* fill y from x[1], ..., x[5] */ static void initsmall(GEN x, GEN y) { GEN a1,a2,a3,a4,a6, b2,b4,b6,b8, c4,c6, D, j, a11, a13, a33, b22; checkell5(x); gel(y,1) = a1 = gel(x,1); gel(y,2) = a2 = gel(x,2); gel(y,3) = a3 = gel(x,3); gel(y,4) = a4 = gel(x,4); gel(y,5) = a6 = gel(x,5); a11 = gsqr(a1); b2 = gadd(a11, gmul2n(a2,2)); gel(y,6) = b2; /* a1^2 + 4a2 */ a13 = gmul(a1, a3); b4 = gadd(a13, gmul2n(a4,1)); gel(y,7) = b4; /* a1 a3 + 2a4 */ a33 = gsqr(a3); b6 = gadd(a33, gmul2n(a6,2)); gel(y,8) = b6; /* a3^2 + 4 a6 */ b8 = gsub(gadd(gmul(a11,a6), gmul(b6, a2)), gmul(a4, gadd(a4,a13))); gel(y,9) = b8; /* a1^2 a6 + 4a6 a2 + a2 a3^2 + 4 a6 - a4(a4 + a1 a3) */ b22 = gsqr(b2); c4 = gadd(b22, gmulsg(-24,b4)); gel(y,10) = c4; /* b2^2 - 24 b4 */ c6 = gadd(gmul(b2,gsub(gmulsg(36,b4),b22)), gmulsg(-216,b6)); gel(y,11) = c6; /* 36 b2 b4 - b2^3 - 216 b6 */ D = gsub(gmul(b4, gadd(gmulsg(9,gmul(b2,b6)),gmulsg(-8,gsqr(b4)))), gadd(gmul(b22,b8),gmulsg(27,gsqr(b6)))); gel(y,12) = D; if (gequal0(D)) pari_err(talker,"singular curve in ellinit"); j = gdiv(gmul(gsqr(c4),c4), D); gel(y,13) = j; } 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) ~ E0 */ /* e1 = ell_realroot(e) */ static GEN new_coords(GEN e, GEN x, GEN e1, GEN *pta, GEN *ptb, int flag, long prec) { GEN b2 = ell_get_b2(e), a, b, p1, p2, w; long ty = typ(e1); p2 = gmul2n(gadd(gmulsg(12,e1), b2), -2); /* = (12 e1 + b2) / 4 */ if (ty == t_PADIC) w = gel(e,18); else { GEN b4 = ell_get_b4(e); if (!is_const_t(ty)) pari_err(typeer,"zell"); /* w^2 = 2b4 + 2b2 e1 + 12 e1^2 = 4(e1-e2)(e1-e3) */ w = sqrtr( gmul2n(gadd(b4, gmul(e1,gadd(b2, mulur(6,e1)))),1) ); if (gsigne(p2) > 0) setsigne(w, -1); } *pta = a = gmul2n(gsub(w,p2),-2); *ptb = b = gmul2n(w,-1); /* = sqrt( (e1 - e2)(e1 - e3) ) */ if (!x) return NULL; if (flag) { GEN d = gsub(a,b); p1 = gadd(x, gmul2n(gadd(gmul2n(e1,2), b2),-3)); p1 = gmul2n(p1,-1); p1 = gadd(p1, gsqrt(gsub(gsqr(p1), gmul(a,d)), prec)); return gmul(p1, gsqr(gmul2n(gaddsg(1,gsqrt(gdiv(gadd(p1,d),p1),prec)),-1))); } x = gsub(x, e1); p1 = gadd(x, b); return gmul2n(gadd(p1, gsqrt(gsub(gsqr(p1), gmul2n(gmul(a,x),2)),prec)), -1); } /* a1, b1 are non-0 t_REALs */ static GEN do_agm(GEN *ptx, GEN a1, GEN b1) { const long s = signe(b1), l = minss(lg(a1), lg(b1)), G = 6 - bit_accuracy(l); GEN p1, a, b, x; x = gmul2n(subrr(a1,b1),-2); if (!signe(x)) pari_err(precer,"ellinit"); for(;;) { GEN d; a = a1; b = b1; b1 = sqrtr(mulrr(a,b)); setsigne(b1, s); a1 = gmul2n(addrr(addrr(a,b), gmul2n(b1,1)),-2); d = subrr(a1,b1); if (!signe(d)) break; p1 = sqrtr( divrr(addrr(x,d),x) ); x = mulrr(x, sqrr(addsr(1,p1))); setexpo(x, expo(x)-2); if (expo(d) <= G + expo(b1)) break; } *ptx = x; return ginv(gmul2n(a1,2)); } /* a1, b1 are t_PADICs */ static GEN do_padic_agm(GEN *ptx, GEN a1, GEN b1, GEN p) { GEN p1, a, b, bmod1, bmod = modii(gel(b1,4),p), x = *ptx; long mi; if (!x) x = gmul2n(gsub(a1,b1),-2); if (gequal0(x)) pari_err(precer,"ellinit"); mi = minss(precp(a1),precp(b1)); for(;;) { GEN d; a = a1; b = b1; b1 = gprec(Qp_sqrt(gmul(a,b)),mi); bmod1 = modii(gel(b1,4),p); if (!equalii(bmod1,bmod)) b1 = gneg_i(b1); a1 = gprec(gmul2n(gadd(gadd(a,b),gmul2n(b1,1)),-2),mi); d = gsub(a1,b1); if (gequal0(d)) break; p1 = Qp_sqrt(gdiv(gadd(x,d),x)); if (! gequal1(modii(gel(p1,4),p))) p1 = gneg_i(p1); x = gmul(x, gsqr(gmul2n(gaddsg(1,p1),-1))); } *ptx = x; return ginv(gmul2n(a1,2)); } GEN ellinit_padic(GEN x, GEN p, long prec) { GEN y, j, b2, b4, c4, c6, p1, w, pv, a1, b1, x1, u2, q, e0, e1; long i, alpha; y = cgetg(20,t_VEC); initsmall(x,y); /* convert now, not before initsmall: better accuracy */ for (i=1; i<=13; i++) if (typ(gel(y,i)) != t_PADIC) gel(y,i) = cvtop(gel(y,i), p, prec); j = ell_get_j(y); if (gequal0(j) || valp(j) >= 0) /* p | j */ pari_err(talker,"valuation of j must be negative in p-adic ellinit"); if (equaliu(p,2)) { pv = utoipos(4); pari_err(impl,"ellinit for 2-adic numbers"); } else pv = p; b2 = ell_get_b2(y); b4 = ell_get_b4(y); c4 = ell_get_c4(y); c6 = ell_get_c6(y); alpha = valp(c4) >> 1; setvalp(c4,0); setvalp(c6,0); e1 = gdiv(c6, gmulsg(6,c4)); c4 = gdivgs(c4,48); c6 = gdivgs(c6,864); do { GEN e2 = gsqr(e1); e0 = e1; /* (c6 + 2e1^3) / (3e1^2 - c4) */ e1 = gdiv(gadd(gmul2n(gmul(e0,e2),1),c6), gsub(gmulsg(3,e2),c4)); } while (!gequal(e0,e1)); setvalp(e1, valp(e1)+alpha); e1 = gsub(e1, gdivgs(b2,12)); w = Qp_sqrt(gmul2n(gadd(b4,gmul(e1,gadd(b2,gmulsg(6,e1)))),1)); p1 = gaddgs(gdiv(gmulsg(3,e0),w),1); if (valp(p1) <= 0) w = gneg_i(w); gel(y,18) = w; a1 = gmul2n(gsub(w,gadd(gmulsg(3,e1),gmul2n(b2,-2))),-2); b1 = gmul2n(w,-1); x1 = NULL; u2 = do_padic_agm(&x1,a1,b1,pv); p1 = ginv(gmul2n(gmul(u2,x1),1)); w = gaddsg(1,p1); q = Qp_sqrt(gmul(p1, gaddgs(p1,2))); /* sqrt(w^2 - 1) */ p1 = gadd(w,q); q = gequal0(p1)? gsub(w,q): p1; if (valp(q) < 0) q = ginv(q); gel(y,14) = mkvec(e1); gel(y,15) = u2; gel(y,16) = ((valp(u2)&1) || kronecker(gel(u2,4),p) <= 0)? gen_0: Qp_sqrt(u2); gel(y,17) = q; gel(y,19) = gen_0; return y; } static void set_dummy(GEN y) { gel(y,14)=gel(y,15)=gel(y,16)=gel(y,17)=gel(y,18)=gel(y,19) = gen_0; } static long base_ring(GEN x, GEN *pp, long *prec) { long i, e = LONG_MAX; GEN p = NULL; for (i = 1; i <= 5; i++) { GEN q = gel(x,i); switch(typ(q)) { case t_PADIC: { long e2 = signe(q[4])? precp(q)+valp(q): valp(q); if (e2 < e) e = e2; if (!p) p = gel(q,2); else if (!equalii(p, gel(q,2))) pari_err(talker,"incompatible p-adic numbers in ellinit"); break; } case t_INT: case t_REAL: case t_FRAC: break; default: /* base ring too general */ *prec = 0; break; } } if (p) { *pp = p; *prec = e; return t_PADIC; } return t_REAL; } GEN ellinit_real(GEN x, long prec) { GEN y, D, R, T, w, a1, b1, x1, u2, q, pi2, aw1, w1, w2; long PREC, e; y = cgetg(20,t_VEC); initsmall(x,y); if (!prec) { set_dummy(y); return y; } D = gel(y,12); switch(typ(D)) { case t_INT: e = expi(D); break; case t_FRAC:e = maxss(expi(gel(D,1)), expi(gel(D,2))); break; default: e = -1; break; } PREC = prec; if (e > 0) PREC += nbits2nlong(e >> 1); R = cleanroots(RHSpol(y), PREC); /* sort roots in decreasing order */ if (gsigne(D) > 0) gen_sort_inplace(R, NULL, &invcmp, NULL); gel(y,14) = R; (void)new_coords(y, NULL, gel(R,1), &a1, &b1, 0, 0); u2 = do_agm(&x1,a1,b1); /* 1/4M */ pi2 = Pi2n(1, prec); aw1 = mulrr(pi2, sqrtr_abs(u2)); w1 = (signe(u2) < 0)? aw1: mkcomplex(gen_0,aw1); w = addsr(1, invr(shiftr(mulrr(u2,x1),1))); q = sqrtr( subrs(sqrr(w), 1) ); /* real or pure imaginary */ /* same formula, split in two branches for efficiency */ if (typ(q) == t_REAL) { GEN t, aw1t, aux; q = (signe(w) > 0)? addrr(w, q): subrr(w, q); /* if |q| > 1, we should have replaced it by 1/q. Instead, we change * the sign of log(q) */ t = divrr(logr_abs(q), pi2); setsigne(t, -1); /* t = log|q|/2Pi, |q|<1 */ /* w2 = w1 I log(q)/2Pi = I w1 t [- w1/2 if q < 0] */ aw1t = mulrr(aw1,t); /* < 0 */ aux = (signe(q) < 0)? negr(shiftr(aw1,-1)): gen_0; if (typ(w1) == t_COMPLEX) w2 = mkcomplex(negr(aw1t), aux); else w2 = mkcomplex(aux, aw1t); } else { /* FIXME: I believe this can't happen */ GEN t; if (signe(w) < 0) togglesign(q); q = mkcomplex(w, q); t = mulcxI(gdiv(glog(q,prec), pi2)); /* we want -t to belong to Poincare's half plane */ if (signe(gel(t,2)) > 0) t = gneg(t); w2 = gmul(w1, t); } if (typ(w1) == t_COMPLEX) w1 = shiftr(gel(w2,1), 1); gel(y,15) = w1; /* > 0 */ gel(y,16) = w2; T = elleta(mkvec2(w1,w2), prec); gel(y,17) = gel(T,1); gel(y,18) = gel(T,2); gel(y,19) = absr(mulrr(w1, gel(w2,2))); return y; } static GEN get_ell(GEN x) { switch(typ(x)) { case t_STR: return gel(ellsearchcurve(x),2); case t_VEC: switch(lg(x)) { case 6: case 14: case 20: return x; } /*fall through*/ } pari_err(talker, "not an elliptic curve (ell5) in ellxxx"); return NULL;/*not reached*/ } GEN smallellinit(GEN x) { pari_sp av = avma; GEN y = cgetg(14,t_VEC); initsmall(get_ell(x),y); return gerepilecopy(av,y); } GEN ellinit(GEN x, long prec) { pari_sp av = avma; long tx; GEN p, y; x = get_ell(x); tx = base_ring(x, &p, &prec); y = (tx == t_PADIC)? ellinit_padic(x, p, prec): ellinit_real(x, prec); return gerepilecopy(av, y); } GEN ellinit0(GEN x, long flag,long prec) { switch(flag) { case 0: return ellinit(x,prec); case 1: return smallellinit(x); default: pari_err(flagerr,"ellinit"); } return NULL; /* not reached */ } /********************************************************************/ /** **/ /** Coordinate Change **/ /** **/ /********************************************************************/ /* [1,0,0,0] */ static GEN init_ch(void) { GEN v = cgetg(5, t_VEC); gel(v,1) = gen_1; gel(v,2) = gel(v,3) = gel(v,4) = gen_0; return v; } static GEN coordch4(GEN e, GEN u, GEN r, GEN s, GEN t) { GEN a1 = ell_get_a1(e); GEN a2 = ell_get_a2(e); GEN b4 = ell_get_b4(e); GEN b6 = ell_get_b6(e); GEN R, y, p1, p2, v, v2, v3, v4, v6, r2, b2r, rx3 = gmulsg(3,r); long i, lx = lg(e); y = cgetg(lx,t_VEC); v = ginv(u); v2 = gsqr(v); v3 = gmul(v,v2); v4 = gsqr(v2); v6 = gsqr(v3); /* A1 = (a1 + 2s) / u */ gel(y,1) = gmul(v,gadd(a1,gmul2n(s,1))); /* A2 = (a2 + 3r - (a1 s + s^2)) / u^2 */ gel(y,2) = gmul(v2,gsub(gadd(a2,rx3),gmul(s,gadd(a1,s)))); p2 = ellLHS0(e,r); p1 = gadd(gmul2n(t,1), p2); /* A3 = (2t + a1 r + a3) / u^3 */ gel(y,3) = gmul(v3,p1); p1 = gsub(ell_get_a4(e),gadd(gmul(t,a1),gmul(s,p1))); /* A4 = (a4 - (a1 t + s (2t + a1 r + a3)) + 2a2 r + 3r^2) / u^4 */ gel(y,4) = gmul(v4,gadd(p1,gmul(r,gadd(gmul2n(a2,1),rx3)))); /* A6 = (r^3 + a2 r^2 + a4 r + a6 - t(t + a1 r + a3)) / u^6 */ gel(y,5) = gmul(v6,gsub(ellRHS(e,r), gmul(t,gadd(t, p2)))); if (lx == 6) return y; if (lx < 14) pari_err(talker,"not an elliptic curve in coordch"); /* B2 = (b2 + 12r) / u^2 */ gel(y,6) = gmul(v2,gadd(ell_get_b2(e),gmul2n(rx3,2))); b2r = gmul(r, ell_get_b2(e)); r2 = gsqr(r); /* B4 = (b4 + b2 r + 6r^2) / u^4 */ gel(y,7) = gmul(v4,gadd(b4,gadd(b2r, gmulsg(6,r2)))); /* B6 = (b6 + 2b4 r + 2b2 r^2 + 4r^3) / u^6 */ gel(y,8) = gmul(v6,gadd(b6,gmul(r,gadd(gmul2n(b4,1), gadd(b2r,gmul2n(r2,2)))))); /* B8 = (b8 + 3b6r + 3b4 r^2 + b2 r^3 + 3r^4) / u^8 */ p1 = gadd(gmulsg(3,b4),gadd(b2r, gmulsg(3,r2))); gel(y,9) = gmul(gsqr(v4), gadd(ell_get_b8(e), gmul(r,gadd(gmulsg(3,b6), gmul(r,p1))))); gel(y,10) = gmul(v4,ell_get_c4(e)); gel(y,11) = gmul(v6,ell_get_c6(e)); gel(y,12) = gmul(gsqr(v6),ell_get_disc(e)); gel(y,13) = ell_get_j(e); if (lx == 14) return y; if (lx < 20) pari_err(talker,"not an elliptic curve in coordch"); R = ell_get_roots(e); if (typ(R) != t_COL) set_dummy(y); else if (typ(e[1])==t_PADIC) { gel(y,14) = mkvec( gmul(v2, gsub(gel(R,1),r)) ); gel(y,15) = gmul(gel(e,15), gsqr(u)); gel(y,16) = gmul(gel(e,16), u); gel(y,17) = gel(e,17); gel(y,18) = gmul(gel(e,18), v2); gel(y,19) = gen_0; } else { p2 = cgetg(4,t_COL); for (i=1; i<=3; i++) gel(p2,i) = gmul(v2, gsub(gel(R,i),r)); gel(y,14) = p2; gel(y,15) = gmul(gel(e,15), u); gel(y,16) = gmul(gel(e,16), u); gel(y,17) = gdiv(gel(e,17), u); gel(y,18) = gdiv(gel(e,18), u); gel(y,19) = gmul(gel(e,19), gsqr(u)); } return y; } static GEN _coordch(GEN e, GEN w) { return coordch4(e, gel(w,1), gel(w,2), gel(w,3), gel(w,4)); } GEN ellchangecurve(GEN e, GEN w) { pari_sp av = avma; checkch(w); checkell5(e); return gerepilecopy(av, _coordch(e, w)); } /* accumulate the effects of variable changes [u,r,s,t] and [U,R,S,T], all of * them integers. Frequent special cases: (U = 1) or (r = s = t = 0) */ static void cumulev(GEN *vtotal, GEN u, GEN r, GEN s, GEN t) { GEN U2,U,R,S,T, v = *vtotal; pari_sp av; U = gel(v,1); R = gel(v,2); S = gel(v,3); T = gel(v,4); if (gequal1(U)) { gel(v,1) = u; gel(v,2) = addii(R, r); gel(v,3) = addii(S, s); av = avma; gel(v,4) = gerepileuptoint(av, addii(T, addii(t, mulii(S, r)))); } else if (!signe(r) && !signe(s) && !signe(t)) gel(v,1) = mulii(U, u); else /* general case */ { U2 = sqri(U); gel(v,1) = mulii(U, u); gel(v,2) = addii(R, mulii(U2, r)); gel(v,3) = addii(S, mulii(U, s)); gel(v,4) = addii(T, mulii(U2, addii(mulii(U, t), mulii(S, r)))); } } /* as above, no assumption */ static void gcumulev(GEN *vtotal, GEN w) { GEN u,r,s,t,U2,U,R,S,T, v = *vtotal; u = gel(w,1); r = gel(w,2); s = gel(w,3); t = gel(w,4); U = gel(v,1); gel(v,1) = gmul(U, u); U2 = gsqr(U); R = gel(v,2); gel(v,2) = gadd(R, gmul(U2, r)); S = gel(v,3); gel(v,3) = gadd(S, gmul(U, s)); T = gel(v,4); gel(v,4) = gadd(T, gmul(U2, gadd(gmul(U, t), gmul(S, r)))); } static void cumule(GEN *vtotal, GEN *e, GEN u, GEN r, GEN s, GEN t) { *e = coordch4(*e, u, r, s, t); cumulev(vtotal, u, r, s, t); } /* X = (x-r)/u^2 * Y = (y - s(x-r) - t) / u^3 */ static GEN ellchangepoint0(GEN x, GEN v2, GEN v3, GEN r, GEN s, GEN t) { GEN p1,z; if (ell_is_inf(x)) return x; z = cgetg(3,t_VEC); p1 = gsub(gel(x,1),r); gel(z,1) = gmul(v2, p1); gel(z,2) = gmul(v3, gsub(gel(x,2), gadd(gmul(s,p1),t))); return z; } 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(typeer,"ellchangepoint"); checkch(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(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 - bit_accuracy(pr) + 15 || expx < ellexpo(e) - bit_accuracy(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(talker, "neither a point nor a vector of points in ellisoncurve"); lx = lg(x); if (lx==1) return cgetg(1,tx); tx = typ(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 invell(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 subell(GEN e, GEN z1, GEN z2) { pari_sp av = avma; checkell5(e); checkellpt(z2); return gerepileupto(av, addell(e, z1, invell(e,z2))); } /* e an ell5, x a scalar */ static GEN ellordinate_i(GEN e, GEN x, long prec) { long td; pari_sp av = avma; GEN D, a, b, d, y; a = ellRHS(e,x); b = ellLHS0(e,x); /* y*(y+b) = a */ D = gadd(gsqr(b), gmul2n(a,2)); td = typ(D); if (td == t_INTMOD && equaliu(gel(D,1), 2)) { /* curve over F_2 */ avma = av; if (!signe(D[2])) { y = cgetg(2,t_VEC); gel(y,1) = mkintmodu(gequal0(a)?0:1, 2); } else { if (!gequal0(a)) return cgetg(1,t_VEC); y = cgetg(3,t_VEC); gel(y,1) = mkintmodu(0,2); gel(y,2) = mkintmodu(1,2); } return y; } if (td == t_FFELT && equaliu(FF_p_i(D),2)) { GEN F = FFX_roots(mkpoln(3, gen_1, b, gneg(a)), D); if (lg(F) == 1) { avma = av; return cgetg(1,t_VEC); } return gerepileupto(av, F); } if (gequal0(D)) { b = gneg_i(b); y = cgetg(2,t_VEC); gel(y,1) = gmul2n(b,-1); return gerepileupto(av,y); } switch(td) { case t_INT: if (!Z_issquareall(D,&d)) { avma = av; return cgetg(1,t_VEC); } break; case t_FRAC: if (gissquareall(D,&d) == gen_0) { avma = av; return cgetg(1,t_VEC); } break; case t_FFELT: if (!FF_issquareall(D,&d)) { avma = av; return cgetg(1,t_VEC); } break; case t_INTMOD: if (kronecker(gel(D,2),gel(D,1)) < 0) { avma = av; return cgetg(1,t_VEC); } /* fall through */ 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) { checkell5(e); if (is_matvec_t(typ(x))) { long i, lx; GEN v = cgetg_copy(x, &lx); for (i=1; i 1) break; } return gerepilecopy(av, mkvec2(x, gel(y,1))); default: pari_err(impl,"random point on elliptic curve over an infinite field"); } return NULL; /* not reached */ } /* n t_QUAD or t_COMPLEX, z != [0] */ static GEN ellpow_CM(GEN e, GEN z, GEN n) { GEN p1p, q1p, x, y, p0, p1, q0, q1, z1, z2, grdx, b2ov12, N = gnorm(n); long ln, ep, vn; if (typ(N) != t_INT) pari_err(typeer,"powell (non integral CM exponent)"); ln = itos_or_0(shifti(addsi(1, N), 3)); if (!ln) pari_err(talker, "norm too large in CM"); vn = ((ln>>1)-4)>>2; z1 = weipell(e, 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(talker,"not a complex multiplication in powell"); 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 addell((GEN)e, x, x); } static GEN _mul(void *e, GEN x, GEN y) { return addell((GEN)e, x, y); } /* [n] z, n integral */ static GEN ellpow_Z(GEN e, GEN z, GEN n) { long s; if (ell_is_inf(z)) return ellinf(); s = signe(n); if (!s) return ellinf(); if (s < 0) z = invell(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_accuracy(lg(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 w1, w2, tau, D, v, x, y, F, dF, q, r, fk, fkb, fkc; long prec; if (!ell_is_real(E)) 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 */ w1 = gel(E,15); w2 = gel(E,16); tau = gdiv(w2, w1); 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 ellpow_CM_aux(GEN e, GEN z, GEN a, GEN w) { GEN A, B, q; if (typ(a) != t_INT) pari_err(typeer,"ellpow_Z"); q = CM_factor(e, w); if (!q) pari_err(talker,"not a complex multiplication in powell"); 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(typeer,"ellpow_CM"); 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 = ellpow_Z(e,z,a); B = ellpow_CM(e,z,w); if (q != gen_1) B = ellpow_Z(e, B, q); return addell(e, A, B); } GEN powell(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, ellpow_Z(e,z,n)); case t_QUAD: { GEN pol = gel(n,1), a = gel(n,2), b = gel(n,3); if (signe(pol[2]) < 0) pari_err(typeer,"ellpow_CM"); /* disc > 0 ? */ return gerepileupto(av, ellpow_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, ellpow_CM_aux(e,z,a,mkcomplex(gen_0,b))); } } pari_err(typeer,"powell (non integral, non CM exponent)"); return NULL; /* not reached */ } /********************************************************************/ /** **/ /** ELLIPTIC FUNCTIONS **/ /** **/ /********************************************************************/ static GEN quot(GEN x, GEN y) { GEN z = mpdiv(x, y), q = floorr(z); if (gsigne(y) < 0 && !gequal(z, q)) q = addis(q, 1); return q; } GEN zell(GEN e, GEN z, long prec) { long ty, sw, fl; pari_sp av = avma; GEN t, u, p1, p2, a, b, x1, u2, D; checkell(e); checkellpt(z); D = ell_get_disc(e); ty = typ(D); if (ty == t_INTMOD) pari_err(typeer,"zell"); if (ell_is_inf(z)) return (ty==t_PADIC)? gen_1: gen_0; x1 = new_coords(e,gel(z,1),ell_realroot(e), &a,&b,1, prec); if (ty==t_PADIC) { u2 = do_padic_agm(&x1,a,b,gel(D,2)); if (!gequal0(gel(e,16))) { t = Qp_sqrt(gaddsg(1, gdiv(x1,a))); t = gdiv(gaddsg(-1,t), gaddsg(1,t)); } else t = gaddsg(2, ginv(gmul(u2,x1))); return gerepileupto(av,t); } sw = gsigne(real_i(b)); fl=0; for(;;) /* ~ agm */ { GEN a0 = a, b0 = b, x0 = x1, d; b = gsqrt(gmul(a0,b0),prec); if (gsigne(real_i(b)) != sw) b = gneg_i(b); a = gmul2n(gadd(gadd(a0,b0),gmul2n(b,1)),-2); d = gsub(a,b); if (gequal0(d) || gexpo(d) < gexpo(a) - bit_accuracy(prec) + 5) break; p1 = gsqrt(gdiv(gadd(x0,d),x0),prec); x1 = gmul(x0,gsqr(gmul2n(gaddsg(1,p1),-1))); d = gsub(x1,x0); if (gequal0(d) || gexpo(d) < gexpo(x1) - bit_accuracy(prec) + 5) { if (fl) break; fl = 1; } else fl = 0; } u = gdiv(x1,a); t = gaddsg(1,u); if (gequal0(t) || gexpo(t) < 5 - bit_accuracy(prec)) t = gen_m1; else t = gdiv(u,gsqr(gaddsg(1,gsqrt(t,prec)))); u = gsqrt(ginv(gmul2n(a,2)),prec); t = gmul(u, glog(t,prec)); /* which square root? test the reciprocal function (pointell) */ if (!gequal0(t)) { GEN z1, z2; int bad; z1 = pointell(e,gprec_w(t,3),3); /* we don't need much precision */ if (ell_is_inf(z1)) pari_err(precer, "ellpointtoz"); /* Either z = z1 (ok: keep t), or z = z2 (bad: t <-- -t) */ z2 = invell(e, z1); bad = (gexpo(gsub(z,z1)) > gexpo(gsub(z,z2))); if (bad) t = gneg(t); if (DEBUGLEVEL) { if (DEBUGLEVEL>4) { err_printf(" z = %Ps\n",z); err_printf(" z1 = %Ps\n",z1); err_printf(" z2 = %Ps\n",z2); } err_printf("ellpointtoz: %s square root\n", bad? "bad": "good"); err_flush(); } } /* send t to the fundamental domain if necessary */ p2 = quot(imag_i(t), imag_i(gel(e,16))); if (signe(p2)) t = gsub(t, gmul(p2, gel(e,16))); p2 = quot(real_i(t), gel(e,15)); if (signe(p2)) t = gsub(t, gmul(p2, gel(e,15))); return gerepileupto(av,t); } typedef struct { 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; /* tau in F = h/Sl2, tau = g.t, g=[a,b;c,d] in SL(2,Z) */ GEN x,y; /* z/w2 defined mod <1,tau> --> z + x tau + y reduced mod <1,tau> */ int swap; /* 1 if we swapped w1 and w2 */ } SL2_red; /* compute gamma in SL_2(Z) gamma(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(SL2_red *T) { long s; T->tau = gdiv(T->w1,T->w2); s = gsigne(imag_i(T->tau)); if (!s) pari_err(talker,"w1 and w2 R-linearly dependent in elliptic function"); 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); } static int get_periods(GEN e, SL2_red *T) { long tx = typ(e); if (is_vec_t(tx)) switch(lg(e)) { case 3: T->w1 = ell_get_a1(e); T->w2 = ell_get_a2(e); red_modSL2(T); return 1; case 20: T->w1 = gel(e,15); T->w2 = gel(e,16);red_modSL2(T); return 1; } return 0; } /* 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 */ static 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; 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) <= - bit_accuracy(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(SL2_red *T, long k, long prec) { GEN y = trueE(T->Tau, k, prec); y = gmul(y, gpowgs(mulcxI(gdiv(Pi2n(1,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 p1, y; SL2_red T; if (k&1 || k<=0) pari_err(talker,"k not a positive even integer in elleisnum"); if (!get_periods(om, &T)) pari_err(typeer,"elleisnum"); y = _elleisnum(&T, k, prec); if (k==2 && signe(T.c)) { p1 = gmul(Pi2n(1,prec), mului(12, T.c)); y = gsub(y, mulcxI(gdiv(p1, 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 [w1,w2] */ static GEN _elleta(SL2_red *T, long prec) { GEN y, y1, y2, e2 = gdivgs(_elleisnum(T,2,prec), 12); y2 = gmul(T->W2, e2); y1 = gadd(PiI2div(T->W2, prec), gmul(T->W1,e2)); y = cgetg(3,t_VEC); gel(y,1) = gneg(y1); gel(y,2) = gneg(y2); return y; } /* compute eta1, eta2 */ GEN elleta(GEN om, long prec) { pari_sp av = avma; GEN y1, y2, E2, pi; SL2_red T; if (typ(om) == t_VEC && lg(om) == 20) return mkvec2copy(gel(om,17), gel(om,18)); if (!get_periods(om, &T)) pari_err(typeer,"elleta"); pi = mppi(prec); E2 = trueE(T.Tau, 2, 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)); return gerepilecopy(av, mkvec2(y1,y2)); } static GEN reduce_z(GEN z, SL2_red *T) { GEN Z = gdiv(z, T->W2); long t = typ(z), pr; if (!is_scalar_t(t) || t == t_INTMOD || t == t_PADIC || t == t_POLMOD) pari_err(typeer,"reduction mod SL2 (reduce_z)"); T->x = ground(gdiv(imag_i(Z), imag_i(T->Tau))); Z = gsub(Z, gmul(T->x,T->Tau)); T->y = ground(real_i(Z)); Z = gsub(Z, T->y); pr = gprecision(Z); if (gequal0(Z) || (pr && gexpo(Z) < 5 - bit_accuracy(pr))) Z = NULL; /*z in L*/ return 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 weipellnumall(SL2_red *T, GEN z, long flall, long prec0) { long toadd, prec; pari_sp av=avma, lim, av1; GEN p1, pi2, q, u, y, yp, u1, u2, qn, v; z = reduce_z(z, T); if (!z) return NULL; prec = precision(z); if (!prec) { prec = precision(T->tau); if (!prec) prec = prec0; } /* 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, z, prec); u1= gsubsg(1,u); u2 = gsqr(u1); y = gadd(mkfrac(gen_1, utoipos(12)), gdiv(u,u2)); if (flall) yp = gdiv(gadd(gen_1,u), gmul(u1,u2)); toadd = (long)ceil(9.065*gtodouble(imag_i(z))); av1 = avma; lim = stack_lim(av1,1); qn = q; for(;;) { GEN qnu,qnu1,qnu2,qnu3,qnu4; qnu = gmul(qn,u); /* q^n u */ qnu1 = gsubsg(1,qnu); /* 1 - q^n u */ qnu2 = gsqr(qnu1); /* (1 - q^n u)^2 */ qnu3 = gsub(qn,u); /* q^n - u */ qnu4 = gsqr(qnu3); /* (q^n - u)^2 */ p1 = gsub(gmul(u, gadd(ginv(qnu2),ginv(qnu4))), gmul2n(ginv(gsqr(gsubsg(1,qn))), 1)); y = gadd(y, gmul(qn,p1)); if (flall) { p1 = gadd(gdiv(gadd(gen_1,qnu),gmul(qnu1,qnu2)), gdiv(gadd(qn,u),gmul(qnu3,qnu4))); yp = gadd(yp, gmul(qn,p1)); } qn = gmul(q,qn); if (gexpo(qn) <= - bit_accuracy(prec) - 5 - toadd) break; if (low_stack(lim, stack_lim(av1,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"weipellnum"); 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 (flall) { yp = gmul(u, gmul(gmul(u1,u2),yp));/* yp *= u (2i pi / w2)^3 */ v = mkvec2(y, gmul2n(yp,-1)); } else v = y; return gerepilecopy(av, v); } GEN ellzeta(GEN om, GEN z, long prec0) { long toadd, prec; pari_sp av = avma, lim, av1; GEN Z, pi2, q, u, y, qn, et = NULL; SL2_red T; if (!get_periods(om, &T)) pari_err(typeer,"ellzeta"); Z = reduce_z(z, &T); if (!Z) pari_err(talker,"can't evaluate ellzeta at a pole"); prec = precision(Z); if (!prec) { prec = precision(T.tau); if (!prec) prec = prec0; } if (!gequal0(T.x) || !gequal0(T.y)) { et = _elleta(&T,prec); et = gadd(gmul(T.x,gel(et,1)), gmul(T.y,gel(et,2))); } pi2 = Pi2n(1, prec); q = expIxy(pi2, T.Tau, prec); u = expIxy(pi2, Z, prec); y = mulcxmI(gdiv(gmul(gsqr(T.W2),_elleisnum(&T,2,prec)), pi2)); y = gadd(ghalf, gdivgs(gmul(Z,y),-12)); y = gadd(y, ginv(gsubgs(u, 1))); toadd = (long)ceil(9.065*gtodouble(imag_i(Z))); av1 = avma; lim = stack_lim(av1,1); /* y += sum q^n ( u/(u*q^n - 1) + 1/(u - q^n) ) */ for (qn = q;;) { GEN p1 = gadd(gdiv(u,gsubgs(gmul(qn,u),1)), ginv(gsub(u,qn))); y = gadd(y, gmul(qn,p1)); qn = gmul(q,qn); if (gexpo(qn) <= - bit_accuracy(prec) - 5 - toadd) break; if (low_stack(lim, stack_lim(av1,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"ellzeta"); gerepileall(av1,2, &y,&qn); } } y = mulcxI(gmul(gdiv(pi2,T.W2), y)); return et? gerepileupto(av, gadd(y,et)): gerepilecopy(av, y); } /* if flag=0, return ellsigma, otherwise return log(ellsigma) */ GEN ellsigma(GEN w, GEN z, long flag, long prec0) { long toadd, prec; pari_sp av = avma, lim, av1; GEN Z, zinit, p1, pi, pi2, q, u, y, y1, u1, qn, uinv, et, etnew, uhalf; int doprod = (flag >= 2), dolog = (flag & 1); SL2_red T; if (!get_periods(w, &T)) pari_err(typeer,"ellsigma"); Z = reduce_z(z, &T); if (!Z) { if (!dolog) return gen_0; pari_err(talker,"can't evaluate log(ellsigma) at lattice point"); } prec = precision(Z); if (!prec) { prec = precision(T.tau); if (!prec) prec = prec0; } et = _elleta(&T, prec); etnew = gadd(gmul(T.x,gel(et,1)), gmul(T.y,gel(et,2))); pi2 = Pi2n(1,prec); pi = mppi(prec); zinit = gmul(Z,T.W2); p1 = gadd(zinit, gmul2n(gadd(gmul(T.x,T.W1), gmul(T.y,T.W2)),-1)); etnew = gmul(etnew, p1); if (mpodd(T.x) || mpodd(T.y)) etnew = gadd(etnew, mulcxI(pi)); y1 = gadd(etnew, gmul2n(gmul(gmul(Z,zinit),gel(et,2)),-1)); toadd = (long)ceil((2*PI/LOG2) * fabs(gtodouble(imag_i(Z)))); uhalf = expIxy(pi, Z, prec); /* exp(i Pi Z) */ u = gsqr(uhalf); if (doprod) { /* use product */ q = expIxy(pi2, T.Tau, prec); uinv = ginv(u); u1 = gsub(uhalf,ginv(uhalf)); y = mulcxmI(gdiv(gmul(T.W2,u1), pi2)); av1 = avma; lim = stack_lim(av1,1); qn=q; for(;;) { p1 = gmul(gadd(gmul(qn,u),gen_m1),gadd(gmul(qn,uinv),gen_m1)); p1 = gdiv(p1,gsqr(gadd(qn,gen_m1))); y = gmul(y,p1); qn = gmul(q,qn); if (gexpo(qn) <= - bit_accuracy(prec) - 5 - toadd) break; if (low_stack(lim, stack_lim(av1,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"ellsigma"); gerepileall(av1,2, &y,&qn); } } } else { /* use sum */ GEN q8, qn2, urn, urninv; long n; 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); qn = gmul(q,qn); urn = gmul(urn,u); urninv = gmul(urninv,uinv); if (gexpo(qn2) + n*toadd <= - bit_accuracy(prec) - 5) break; if (low_stack(lim, stack_lim(av1,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"ellsigma"); gerepileall(av1,5, &y,&qn,&qn2,&urn,&urninv); } } p1 = gmul(gmul(y,q8), gdiv(mulcxmI(T.W2), gmul(pi2,gpowgs(trueeta(T.Tau,prec),3)))); } y1 = dolog? gadd(y1, glog(p1,prec)): gmul(p1, gexp(y1,prec)); return gerepileupto(av, y1); } GEN pointell(GEN e, GEN z, long prec) { pari_sp av = avma; GEN v; SL2_red T; checkell_real(e); (void)get_periods(e, &T); v = weipellnumall(&T,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); } static GEN _weipell(GEN c4, GEN c6, long PREC) { long i, k, l; pari_sp av; GEN t, res = cgetg(PREC+2,t_SER), *P = (GEN*)(res + 2); res[1] = evalsigne(1) | _evalvalp(-2) | evalvarn(0); if (!PREC) { setsigne(res,0); return res; } for (i=1; i 3) return weipell(e, PREC); c4 = elleisnum(e, 4, 0, prec); c6 = elleisnum(e, 6, 0, prec); c6 = gneg(c6); return _weipell(c4,c6,PREC); } GEN ellwp0(GEN w, GEN z, long flag, long PREC, long prec) { GEN v; pari_sp av = avma; SL2_red T; if (!z) return weipell0(w,prec,PREC); if (typ(z)==t_POL) { if (!gcmpX(z)) pari_err(talker,"expecting a simple variable in ellwp"); v = weipell0(w,prec,PREC); setvarn(v, varn(z)); return v; } if (!get_periods(w, &T)) pari_err(typeer,"ellwp"); switch(flag) { case 0: v = weipellnumall(&T,z,0,prec); if (!v) { avma = av; v = gpowgs(z,-2); } return v; case 1: v = weipellnumall(&T,z,1,prec); if (!v) { GEN p1 = gmul2n(gpowgs(z,3),1); pari_sp tetpil = avma; v = cgetg(3,t_VEC); gel(v,1) = gpowgs(z,-2); gel(v,2) = gneg(p1); return gerepile(av,tetpil,v); } return v; case 2: return pointell(w,z,prec); default: pari_err(flagerr,"ellwp"); return NULL; } } /********************************************************************/ /** **/ /** 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(bugparier, s); pari_err(talker,"not a prime in localred"); return NULL; /* not reached */ } /* Here p > 3. e assumed integral */ static GEN localred_p(GEN e, GEN p, int minim) { long k, f, kod, c, nuj, nuD; GEN p2, v = init_ch(); GEN c4, c6, D, tri; c4 = ell_get_c4(e); c6 = ell_get_c6(e); D = ell_get_disc(e); nuj = gequal0(ell_get_j(e))? 0: - Q_pval(ell_get_j(e), p); nuD = Z_pval(D, p); k = (nuj > 0 ? nuD - nuj : nuD) / 12; if (k <= 0) { if (minim) return v; } 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))); /* a_2' */ 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)); /* - a_3' */ if (mpodd(t)) t = addii(t, mulii(pk, p2k)); t = shifti(t, -1); gel(v,1) = pk; gel(v,2) = r; gel(v,3) = s; gel(v,4) = t; if (minim) return v; 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: f = 2; kod = -4-nuj; /* Inu* */ if (nuj & 1) c = 3 + kronecker(diviiexact(mulii(c6, D),powiu(p, 9+nuj)), p); else c = 3 + kronecker(diviiexact(D, powiu(p, 6+nuj)), p); 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) cumule(&v, &e, gen_1, 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)) cumule(&v, &e, gen_1, gen_0, gen_0, 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) cumule(&v, &e, gen_1, stoi(theroot * p), gen_0, gen_0); /* 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) cumule(&v, &e, gen_1, gen_0, gen_0, 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) cumule(&v, &e, gen_1, mulsi(theroot, pk1), gen_0, gen_0); 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) cumule(&v, &e, gen_1, stoi(theroot*p), gen_0, gen_0); /* 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) cumule(&v, &e, gen_1, gen_0, gen_0, 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* */ cumule(&v, &e, utoipos(p), gen_0, gen_0, gen_0); /* not minimal */ nuD -= 12; } } } static GEN localred(GEN e, GEN p, int minim) { if (cmpiu(p, 3) > 0) /* p != 2,3 */ return localred_p(e,p, minim); else { long l = itos(p); GEN z; if (l < 2) pari_err(talker,"not a prime in localred"); z = localred_23(e, l); return minim? gel(z,3): z; } } GEN elllocalred(GEN e, GEN p) { pari_sp av = avma; checksmallell(e); if (typ(ell_get_disc(e)) != t_INT) pari_err(talker,"not an integral curve in elllocalred"); if (typ(p) != t_INT || signe(p) <= 0) pari_err(typeer,"elllocalred"); return gerepileupto(av, localred(e, p, 0)); } static GEN ellintegralmodel(GEN e) { GEN a = cgetg(6,t_VEC), v, L, u; long i, l, k; checksmallell(e); 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(talker, "not a rational curve in ellintegralmodel"); } } /* a = [a1, a2, a3, a4, a6] */ l = lg(L); if (l == 1) return NULL; L = ZV_sort_uniq(L); l = lg(L); u = 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; } } u = mulii(u, powiu(p, n)); } v = init_ch(); gel(v,1) = ginv(u); return v; } /* e integral model */ static void standard_model(GEN e, GEN *pv) { GEN a1 = ell_get_a1(e), a2 = ell_get_a2(e); GEN r, t, s = truedivis(a1, -2); r = truedivis(addis(subii(a2, mulii(s,addii(s,a1))), 1), -3); t = truedivis(ellLHS0_i(e,r), -2); cumulev(pv, gen_1, r, s, t); } GEN ellminimalmodel(GEN E, GEN *ptv) { pari_sp av = avma; GEN c4, c6, e, v, v0, P; long l, k; v0 = ellintegralmodel(E); e = ell_to_small(E); if (v0) e = _coordch(e, v0); v = init_ch(); c4 = ell_get_c4(e); c6 = ell_get_c6(e); P = gel(Z_factor(gcdii(c4,c6)),1); l = lg(P); for (k = 1; k < l; k++) { GEN w = localred(e, gel(P,k), 1); if (!gequal1(gel(w,1))) cumule(&v, &e, gel(w,1), gel(w,2), gel(w,3), gel(w,4)); } standard_model(e, &v); if (v0) { gcumulev(&v0, v); v = v0; } e = _coordch(E, v); if (ptv) { gerepileall(av, 2, &e, &v); *ptv = v; } else e = gerepilecopy(av, e); return e; } /* Reduction of a rational curve E to its standard minimal model * (a1,a3 = 0 or 1, a2 = -1, 0 or 1). * * Return [N, [u,r,s,t], c], where * N = arithmetic conductor of E * c = product of the local Tamagawa numbers cp * [u, r, s, t] = the change of variable reducing E to its minimal model, * with u > 0 */ GEN ellglobalred(GEN E) { long k, l; pari_sp av = avma; GEN c, P, N, v, v0, e, c4, c6, D; v0 = ellintegralmodel(E); e = ell_to_small(E); if (v0) e = _coordch(e, v0); v = init_ch(); c4 = ell_get_c4(e); c6 = ell_get_c6(e); D = ell_get_disc(e); P = gel(Z_factor(gcdii(c4,c6)),1); l = lg(P); for (k = 1; k < l; k++) (void)Z_pvalrem(D, gel(P,k), &D); if (!is_pm1(D)) P = shallowconcat(P, gel(Z_factor(absi(D)),1)); l = lg(P); c = N = gen_1; for (k = 1; k < l; k++) { GEN p = gel(P,k), q = localred(e, p, 0), w = gel(q,3); N = mulii(N, powii(p, gel(q,1))); c = mulii(c, gel(q,4)); if (!gequal1(gel(w,1))) cumule(&v, &e, gel(w,1), gel(w,2), gel(w,3), gel(w,4)); } standard_model(e, &v); if (v0) { gcumulev(&v0, v); v = v0; } return gerepilecopy(av, mkvec3(N,v,c)); } GEN ell_to_small_red(GEN e, GEN *N) { GEN E = ell_to_small(e), gr = ellglobalred(E); E = _coordch(E,gel(gr,2)); *N = gel(gr,1); return E; } /********************************************************************/ /** **/ /** ROOT NUMBER (after Halberstadt at p = 2,3) **/ /** **/ /********************************************************************/ /* p = 2 or 3 */ static long neron(GEN e, long p, long* ptkod) { long kod, v4, v6, vd; pari_sp av=avma; GEN c4, c6, d, nv; nv = localred_23(e,p); *ptkod = kod = itos(gel(nv,2)); c4=ell_get_c4(e); c6=ell_get_c6(e); d=ell_get_disc(e); v4 = gequal0(c4) ? 12 : Z_lval(c4,p); v6 = gequal0(c6) ? 12 : Z_lval(c6,p); vd = Z_lval(d,p); avma = av; if (p == 2) { 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; } } else { 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 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 ellrootno_2(GEN e) { long n2, kod, u, v, x1, y1, d1, vd, v4, v6; val_init(e, 2, 64, &v4, &u, &v6, &v, &vd, &d1); if (!vd) return 1; n2 = neron(e,2,&kod); if (kod>=5) return odd(umodiu(ell_get_a2(e),2) + umodiu(ell_get_a3(e),2)) ? 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; val_init(e, 3, 81, &v4, &u, &v6, &v, &vd, &d1); if (!vd) return 1; n2 = neron(e,3,&kod); K6 = kross(v,3); if (kod>4) return K6; 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; } } /* assume p > 3, p^ex || N(E) */ static long ellrootno_p(GEN e, GEN p, ulong ex) { GEN j; long ep,z; if (!ex) return 1; if (ex == 1) return -kronecker(negi(ell_get_c6(e)),p); j=ell_get_j(e); if (!gequal0(j) && Q_pval(j,p) < 0) return krosi(-1,p); ep = 12 / ugcd(12, Z_pval(ell_get_disc(e),p)); if (ep==4) z = 2; else z = (ep&1) ? 3 : 1; return krosi(-z, p); } long ellrootno_global(GEN e, GEN N) { long i, v, s = -1; GEN fa, P, E; v = Z_lvalrem(N, 2, &N); if (v) s *= ellrootno_2(e); v = Z_lvalrem(N, 3, &N); if (v) s *= ellrootno_3(e); fa = Z_factor(N); P = gel(fa,1); E = gel(fa,2); for (i=1; i 0) s = ellrootno_p(e,p, Z_pval(N, p)); else switch(itou(p)) { case 2: s = ellrootno_2(e); break; case 3: s = ellrootno_3(e); break; default: s = -1; break; /* local factor at infinity */ } } avma = av; return s; } /********************************************************************/ /** **/ /** TRACE OF FROBENIUS **/ /** **/ /********************************************************************/ /* compute a_2 */ static long a2(GEN e) { /* solve y(1 + a1x + a3) = x (1 + a2 + a4) + a6 */ ulong a1 = Rg_to_Fl(ell_get_a1(e), 2); ulong a2 = Rg_to_Fl(ell_get_a2(e), 2); ulong a3 = Rg_to_Fl(ell_get_a3(e), 2); ulong a4 = Rg_to_Fl(ell_get_a4(e), 2); ulong a6 = Rg_to_Fl(ell_get_a6(e), 2); 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 3 - N; } /* a_p using Jacobi sums */ static long ap_jacobi(GEN e, ulong p) { if (p == 2) return a2(e); else { ulong i; ulong e6 = Rg_to_Fl(ell_get_b2(e), p); ulong e72= Rg_to_Fl(ell_get_b4(e), p) << 1; ulong e8 = Rg_to_Fl(ell_get_b6(e), p); long s = krouu(e8, p) + krouu((e8 + e72 + e6 + 4) % p, p); /* i = 0,1 */ if (p < 757UL) for (i=2; 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(talker,"prime too large: please install the 'seadata' package"); avma = av; return itos(t) >> 1; } /* compute a_p using Shanks/Mestre + Montgomery's trick. Assume p > 457 */ static GEN ellap1(GEN e, 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, c4,c6, a4, pts; tx = NULL; ty = ti = NULL; /* gcc -Wall */ if (DEBUGLEVEL) timer_start(&T); c4 = Rg_to_Fp(gdivgs(ell_get_c4(e), -48), p); c6 = Rg_to_Fp(gdivgs(ell_get_c6(e), -864), p); /* 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, "[ellap1] 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, "[ellap1] 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); ulong m, l = 1, r = s+1; long k, k2, j2; avma = av2; k = mod2BIL(gel(ftest,1)); while (l> 1; if (tx[m] < k) l = m+1; else r = m; } if (r <= (ulong)s && tx[r] == k) { while (tx[r] == k && r) r--; k2 = mod2BIL(gel(ftest,2)); for (r++; tx[r] == k && r <= (ulong)s; 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, "[ellap1] 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? subii(p1p,h): subii(h,p1p)); } typedef struct { int isnull; long x,y; } sellpt; /* P <-- P + Q, safe with P = Q */ static void s_addell(sellpt *P, sellpt *Q, long c4, long p) { ulong num, den, lambda; if (P->isnull) { *P = *Q; return; } if (Q->isnull) return; if (P->x == Q->x) { if (! P->y || P->y != Q->y) { P->isnull = 1; return; } num = Fl_add(c4, Fl_mul(3, Fl_mul(P->x, P->x, p), p), p); den = Fl_add(P->y, P->y, p); } else { num = Fl_sub(P->y, Q->y, p); den = Fl_sub(P->x, Q->x, p); } lambda = Fl_div(num, den, p); num = Fl_sub(Fl_mul(lambda, lambda, p), Fl_add(P->x, Q->x, p), p); P->y = Fl_sub(Fl_mul(lambda, Fl_sub(Q->x, num, p), p), Q->y, p); P->x = num; /* necessary in case P = Q: we need Q->x above */ } /* Q <-- P^n */ static void s_powell(sellpt *Q, sellpt *P, long n, long c4, long p) { sellpt R = *P; if (n < 0) { n = -n; if (R.y) R.y = p - R.y; } Q->isnull = 1; Q->x = Q->y = 0; /* -Wall */ for(;;) { if (n&1) s_addell(Q, &R, c4, p); n >>= 1; if (!n) return; s_addell(&R, &R, c4, p); } } /* assume H.f = 0, return exact order of f, cf. exact_order */ static long sexact_order(long H, sellpt *f, long c4, long p) { GEN P, e, fa = factoru(H); long h = H, pp, i, j, l; sellpt fh; P = gel(fa,1); l = lg(P); e = gel(fa,2); for (i=1; ix - b->x; } 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 ellap1() */ static long ellap2(GEN e, ulong p) { sellpt f, fh, fg, ftest, F; ulong x, u, c4, c6, cp4, p1p, p2p, h; long pordmin,A,B; long i, s, KRO, KROold, l, r, m; pari_sp av; multiple *table = NULL; av = avma; c4 = Rg_to_Fl(gdivgs(ell_get_c4(e), -48), p); c6 = Rg_to_Fl(gdivgs(ell_get_c6(e), -864), p); pordmin = (long)(1 + 4*sqrt((float)p)); p1p = p+1; p2p = p1p << 1; x = 0; u = c6; KRO = kross(u, p); KROold = -KRO; switch(Flx_nbroots(mkvecsmalln(5,0, 1, 0, c4, c6), 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(talker, "%lu is not prime, use ellak", p); t = Fl_add(c4, Fl_mul(x,x,p), p); u = Fl_add(c6, Fl_mul(x, t, p), p); KRO = kross(u,p); } KROold = KRO; f.isnull = 0; f.x = Fl_mul(x, u, p); f.y = Fl_mul(u, u, p); cp4 = Fl_mul(c4, f.y, p); s_powell(&fh, &f, h, cp4, p); s = (long) (sqrt(((float)pordmin)/B) / 2); if (!s) s = 1; if (!table) { table = (multiple *) pari_malloc((s+1) * sizeof(multiple)); F = f; } s_powell(&F, &f, B, cp4, p); for (i=0; i < s; i++) { if (fh.isnull) { h += B*i; goto FOUND; } table[i].x = fh.x; table[i].y = fh.y; table[i].i = i; s_addell(&fh, &F, cp4, p); } qsort(table,s,sizeof(multiple),(QSCOMP)compare_multiples); s_powell(&fg, &F, s, cp4, p); ftest = fg; for (i=1; ; i++) { if (ftest.isnull) { if (!uisprime(p)) pari_err(talker,"%lu is not prime, use ellak", p); pari_err(bugparier,"ellap (f^(i*s) = 1)"); } l=0; r=s; while (l> 1; if (table[m].x < ftest.x) l=m+1; else r=m; } if (r < s && table[r].x == ftest.x) break; s_addell(&ftest, &fg, cp4, p); } h += table[r].i * B; if (table[r].y == ftest.y) i = -i; h += s * i * B; FOUND: h = sexact_order(h, &f, 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; } if (table) pari_free(table); return KRO==1? p1p-h: h-p1p; } /** 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 E,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 = Rg_to_Fp(gmulgs(ell_get_c6(E), 8), p); e = diviuexact(shifti(p,-1), 3); /* (p-1) / 6 */ return centermod(mulii(a, Fp_pow(d, e, p)), p); } static GEN ap_j1728(GEN E,GEN p) { GEN a, b, d, 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); d = Rg_to_Fp(gmulgs(ell_get_c4(E), -27), p); e = shifti(p,-2); /* (p-1) / 4 */ return centermod(mulii(a, Fp_pow(d, e, p)), p); } static GEN ap_j8000(GEN p) { GEN a, b; long r = mod8(p); 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)) a = negi(a); break; case 10: case 14: if (!Mod4(b)) a = negi(a); break; } return a; } static GEN ap_j287496(GEN p) { GEN a, b; 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); if (krosi(2,p) < 0) a = negi(a); return a; } static GEN ap_cm(int CM, GEN p) { GEN a, b; 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)) a = negi(a); return a; } static GEN ec_ap_cm(GEN J,GEN C6B,GEN C6E,int CM,GEN jd,GEN jn,GEN p) { GEN a; if (!equalii(modii(mulii(jd,J),p), jn)) return NULL; if (CM == -8) a = ap_j8000(p); else if (CM == -16) a = ap_j287496(p); else a = ap_cm(CM,p); if (kronecker(mulii(C6E,C6B), p) < 0) a = negi(a); return a; } static GEN ap_bad_red(GEN e, GEN p) { pari_sp av = avma; GEN c6 = ell_get_c6(e); long s; if (equaliu(p, 2)) { long c; if (!signe(c6)) return gen_0; c = mod8(c6); if (!odd(c)) return gen_0; return (c == 3 || c == 5)? gen_m1: gen_1; } c6 = Rg_to_Fp(c6, p); s = kronecker(c6, p); if (mod4(p) == 3) s = -s; avma = av; return stoi(s); } static GEN u2tonegi(ulong a, ulong b) { GEN z = uu32toi(a,b); setsigne(z, -1); return z; } static GEN CM_ellap(GEN E, GEN p) { pari_sp av = avma; GEN C4E, C6E, j, jn, jd, a, t, u; #define CHECK(CM,J,C6B) a = ec_ap_cm(J,C6B,C6E,CM,jd,jn,p); if (a) goto DONE; C4E = Rg_to_Fp(ell_get_c4(E), p); if (!signe(C4E)) { a = ap_j0(E,p); goto DONE;} C6E = Rg_to_Fp(ell_get_c6(E), p); if (!signe(C6E)) { a = ap_j1728(E,p); goto DONE;} j = ell_get_j(E); jn = Rg_to_Fp(numer(j), p); jd = Rg_to_Fp(denom(j), p); /* j = jn/jd */ CHECK(-7, utoineg(3375), utoipos(1323)); CHECK(-8, utoipos(8000), utoineg(1792)); CHECK(-12, utoipos(54000), utoineg(19008)); CHECK(-11, utoineg(32768), utoineg(6776)); CHECK(-16, utoipos(287496), utoipos(12096)); CHECK(-19, utoineg(884736), utoineg(77976)); CHECK(-27, utoineg(12288000), utoineg(54648)); CHECK(-7, utoipos(16581375), utoipos(75411)); CHECK(-43, utoineg(884736000), utoineg(8387064)); t = u2tonegi(0x00000022UL, 0x45ae8000UL); /* -27878400*5280 */ CHECK(-67, t, utoineg(210408408)); t = u2tonegi(0x03a4b862UL, 0xc4b40000UL); /* -640320^3 */ u = u2tonegi(0x000000f8UL, 0x4414c858UL); /* -705220967*1512 */ CHECK(-163, t, u); #undef CHECK avma = av; return NULL; DONE: return gerepileuptoint(av, icopy(a)); } static GEN easy_ap(GEN E, GEN p) { pari_sp av = avma; GEN D = Rg_to_Fp(ell_get_disc(E), p); avma = av; if (!signe(D)) return ap_bad_red(E,p); if (cmpiu(p, 99) < 0) return stoi(ap_jacobi(E, itou(p))); return CM_ellap(E, p); } /* assume e is at least a 'small ell' */ static GEN get_p(GEN e) { GEN j = ell_get_j(e); switch(typ(j)) { case t_INTMOD: return gel(j,1); case t_PADIC: return gel(j,2); } pari_err(talker,"cannot determine the prime p in elliptic curve function"); return NULL; /*notreached*/ } GEN ellap(GEN e, GEN p) { GEN a; long lp; checksmallell(e); if (!p) p = get_p(e); else if (typ(p)!=t_INT || signe(p) <= 0) pari_err(talker,"not a prime in ellap"); if ( (a = easy_ap(e, p)) ) return a; lp = expi(p); if (lp < 30) return stoi(ellap2(e, itou(p))); if (lp >= 62) { a = ellsea(e, p, 0); if (a) return a; } return ellap1(e, p); } /* assume e has good reduction mod p */ static long ellap_small_goodred(GEN E, ulong p) { pari_sp av; GEN a; if (p < 99) return ap_jacobi(E, p); av = avma; a = CM_ellap(E, utoipos(p)); avma = av; if (a) return itos(a); if (p > 0x3fffffff) { a = ellap1(E, utoipos(p)); avma = av; return itos(a); } return ellap2(E, p); } static void checkell_int(GEN e) { checksmallell(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(talker,"not an integral model"); } GEN anell(GEN e, long n0) { const long tab[4]={0,1,1,-1}; /* p prime; (-1/p) = tab[p&3]. tab[0] unused */ ulong p, m, SQRTn, n = (ulong)n0; GEN an, D, c6; checkell_int(e); if (n0 <= 0) return cgetg(1,t_VEC); if (n >= LGBITS) pari_err(impl,"anell for n >= %lu", LGBITS); SQRTn = (ulong)sqrt(n); c6= ell_get_c6(e); D = ell_get_disc(e); an = cgetg(n+1,t_VEC); gel(an,1) = gen_1; for (p=2; p <= n; p++) gel(an,p) = NULL; for (p=2; p<=n; p++) { if (an[p]) continue; /* p not prime */ if (!umodiu(D,p)) /* bad reduction, p | D */ switch (tab[p&3] * krois(c6,p)) /* (-c6/p) */ { case -1: /* non deployee */ for (m=p; m<=n; m+=p) if (an[m/p]) gel(an,m) = negi(gel(an,m/p)); continue; case 0: /* additive */ for (m=p; m<=n; m+=p) gel(an,m) = gen_0; continue; case 1: /* deployee */ for (m=p; m<=n; m+=p) if (an[m/p]) gel(an,m) = gel(an,m/p); continue; } else /* good reduction */ { long ap = ellap_small_goodred(e, p); if (p <= SQRTn) { ulong pk, oldpk = 1; for (pk=p; pk <= n; oldpk=pk, pk *= p) { if (pk == p) gel(an,pk) = stoi(ap); else { pari_sp av = avma; GEN u = mulsi(ap, gel(an,oldpk)); GEN v = mului(p, gel(an,oldpk/p)); gel(an,pk) = gerepileuptoint(av, subii(u,v)); } for (m = n/pk; m > 1; m--) if (an[m] && m%p) gel(an,m*pk) = mulii(gel(an,m), gel(an,pk)); } } else { gel(an,p) = stoi(ap); for (m = n/p; m > 1; m--) if (an[m]) gel(an,m*p) = mulsi(ap, gel(an,m)); } } } return an; } GEN akell(GEN e, GEN n) { long i, j, s, ex; pari_sp av = avma; GEN fa, P, E, D, c6, ap, u, v, w, y, p; checksmallell(e); if (typ(n) != t_INT) pari_err(typeer,"akell"); if (signe(n)<= 0) return gen_0; if (gequal1(n)) return gen_1; c6= ell_get_c6(e); D = ell_get_disc(e); if (typ(D) != t_INT) pari_err(talker,"not an integral model in akell"); u = coprime_part(n, D); 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; i1) pari_warn(warnmem,"lseriesell"); z = gerepilecopy(av1,z); } } return gerepileupto(av, gdiv(z,gs)); } /********************************************************************/ /** **/ /** CANONICAL HEIGHT **/ /** **/ /********************************************************************/ /* h' := h_oo(a) + 1/2 log(denom(a)) */ static GEN hell(GEN e, GEN a, long prec) { long n; pari_sp av = avma; GEN pi2 = Pi2n(1, prec), w1 = gel(e,15), w2 = gel(e,16); GEN p1, y, z, q, pi2surw, qn, ps; pi2surw = gdiv(pi2, w1); z = gmul(real_i(zell(e,a,prec)), pi2surw); q = real_i( expIxy(mpneg(pi2surw), w2, prec) ); y = mpsin(z); qn = gen_1; ps = gneg_i(q); for (n = 3; ; n += 2) { qn = gmul(qn, ps); ps = gmul(ps, q); y = gadd(y, gmul(qn, gsin(gmulsg(n,z),prec))); if (gexpo(qn) < -bit_accuracy(prec)) break; } p1 = gmul(gsqr(gdiv(gmul2n(y,1), d_ellLHS(e,a))), pi2surw); p1 = gsqr(gsqr(gdiv(p1, gsqr(gsqr(denom(gel(a,1))))))); p1 = gdiv(gmul(p1,q), ell_get_disc(e)); p1 = gmul2n(glog(gabs(p1,prec),prec), -5); return gerepileupto(av, gneg(p1)); } /* h' := h_oo(x) + 1/2 log(denom(x)) */ static GEN hells(GEN e, GEN Q, long prec) { GEN b2 = ell_get_b2(e); GEN b4 = ell_get_b4(e); GEN b6 = ell_get_b6(e); GEN b8 = ell_get_b8(e); GEN x = gel(Q,1), w, z, t, mu, b42, b62; long n, lim; mu = gmul2n(glog(numer(x),prec),-1); t = ginv(gtofp(x, prec)); b42 = gmul2n(b4,1); b62 = gmul2n(b6,1); lim = 15 + bit_accuracy(prec); for (n = 3; n < lim; n += 2) { /* 4 + b2 t + 2b4 t^2 + b6 t^3 */ w = gmul(t, gaddsg(4, gmul(t, gadd(b2, gmul(t, gadd(b42, gmul(t, b6))))))); /* 1 - (b4 t^2 + 2b6 t^3 + b8 t^4) */ z = gsubsg(1, gmul(gsqr(t), gadd(b4, gmul(t, gadd(b62, gmul(t, b8)))))); mu = gadd(mu, gmul2n(glog(z,prec), -n)); t = gdiv(w, z); } return mu; } static GEN hell2(GEN e, GEN x, long prec) { GEN e3, ro, v, D; pari_sp av = avma; if (ell_is_inf(x)) return gen_0; D = ell_get_disc(e); ro= ell_get_roots(e); e3 = (gsigne(D) < 0)? gel(ro,1): gel(ro,3); v = init_ch(); gel(v,2) = addis(gfloor(e3),-1); return gerepileupto(av, hells(_coordch(e,v), ellchangepoint(x,v), prec)); } /* exp( h_oo(z) ), assume z on neutral component. * If flag, return exp(4 h_oo(z)) instead */ static GEN exphellagm(GEN e, GEN z, GEN e1, int flag, long prec) { GEN x_a, a, b, r, V = cgetg(1, t_VEC), x = gel(z,1); long n, ex = 5-bit_accuracy(prec); x = new_coords(e, x, e1, &a,&b, 0, prec); x_a = gsub(x, a); if (gsigne(a) > 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) )); } /* exp( 4h_oo(z) ) */ static GEN exp4hellagm(GEN e, GEN z, long prec) { GEN e1 = ell_realrootprec(e, prec), x = gel(z,1); if (gcmp(x, e1) < 0) /* z not on neutral component */ { GEN eh = exphellagm(e, addell(e, z,z), e1, 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, e1, 1, prec); } GEN ellheightoo(GEN e, GEN z, long prec) { GEN e1, h, x = gel(z,1); pari_sp av = avma; checksmallell_real(e); e1 = ell_realrootprec(e, prec); if (gcmp(x, e1) < 0) /* z not on neutral component */ { GEN eh = exphellagm(e, addell(e, z,z), e1, 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, e1, 1, prec); return gerepileuptoleaf(av, gmul2n(mplog(h), -2)); } /* Assume e integral, given by a minimal model */ 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; if (flag > 2 || flag < 0) pari_err(flagerr,"ellheight"); checksmallell_real(e); if (!is_matvec_t(tx)) pari_err(typeer, "ellheight"); lx = lg(a); if (lx==1) return cgetg(1,tx); tx = typ(a[1]); 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(typeer, "ellheightmatrix"); 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 = ellpow_Z(e,p,utoipos(n)); if (n % 2 && smaller_x(gel(np,1), gel(best,1))) best = np; p1 = addell(e,q,np); if (smaller_x(gel(p1,1), gel(best,1))) q = p1; else if (best == np) { p = addell(e,p,q); q = np; } p = best_in_cycle(e,p,k); if (v) { p = ellchangepoint(p,v); q = ellchangepoint(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 = ellchangepoint(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 _pow(void *E, GEN x, GEN n) { return ellpow_Z((GEN)E,x,n); } static GEN topol(GEN x) { switch(typ(x)) { case t_INTMOD: return gel(x,2); case t_POLMOD: return gtovecrev(gel(x,2)); case t_FFELT: return gtovecrev(FF_to_FpXQ(x)); } return x; } static ulong _hash(GEN x) { pari_sp av; GEN r; ulong h=0; if (ell_is_inf(x)) return 0; av = avma; r = topol(gel(x,1)); if (typ(r)==t_INT) h=signe(r)?mod2BIL(r):0; else { long i, l=lg(r); for (i=1;it) pari_err(bugparier,"elltors (bug1)"); w3 = mkvec( gel(r,k) ); } else { if (t&3) pari_err(bugparier,"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(bugparier,"elltors (bug3)"); p1 = ellpow_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) { long m, b, bold, p = 2; pari_sp av = avma; byteptr diff = diffptr+1; GEN D = ell_get_disc(e); long n = bit_accuracy(lgefint(D)) >> 3; /* n = number of primes to try ~ 1 prime every 8 bits in D */ b = bold = 5040; /* = 2^4 * 3^2 * 5 * 7 */ m = 0; while (m < n) { NEXT_PRIME_VIADIFF_CHECK(p,diff); if (!umodiu(D, p)) continue; b = ugcd(b, p+1 - ellap_small_goodred(e, p)); avma = av; if (b == 1) break; if (b == bold) m++; else { bold = b; m = 0; } } return b; } static GEN myround(GEN x, long *e) { GEN y = grndtoi(x,e); if (*e > -5 && bit_accuracy(gprecision(x)) < gexpo(y) - 10) pari_err(talker, "ellinit data not accurate enough. Increase precision"); 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(p[1]) == t_COMPLEX) return NULL; gel(p,2) = gmul2n(myround(gmul2n(gel(q,2),3), &e),-3); if (e > -5 || typ(p[2]) == t_COMPLEX) return NULL; return (oncurve(E,p) && ell_is_inf(ellpow_Z(E,p,utoipos(n))) && _orderell(E,p) == n)? p: NULL; } GEN elltors(GEN e) { long B, i, ord, pr, prec, k = 1; pari_sp av=avma; GEN v,w,w1,w22,w1j,w12,p,tor1,tor2; checkell_real(e); v = ellintegralmodel(e); if (v) e = _coordch(e,v); B = torsbound(e); /* #E_tor | B */ if (B == 1) { avma = av; return tors(e,1,NULL,NULL, v); } pr = DEFAULTPREC + ((lgefint(ell_get_disc(e))-2) >> 1); /* pr >= size of sqrt(D) */ w1 = gel(e,15); prec = precision(w1); if (pr < prec) { prec = pr; e = gprec_w(e, pr); w1 = gel(e,15); } if (pr > prec) { prec = pr; e = ellinit_real(e, pr); w1 = gel(e,15); } if (v) gel(v,1) = ginv(gel(v,1)); w22 = gmul2n(gel(e,16),-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)); } GEN elltors0(GEN e, long flag) { switch(flag) { case 0: return elltors(e); case 1: return nagelllutz(e); default: pari_err(flagerr,"elltors"); } return NULL; /* not reached */ } /********************************************************************/ /** **/ /** PAIRINGS **/ /** **/ /********************************************************************/ /* Formulae from a GP script by J.E.Cremona */ static GEN ellffvert(GEN t, GEN pt) { return ell_is_inf(t)?gen_1:gsub(gel(pt, 1), gel(t, 1)); } static GEN ellfftang(GEN E, GEN t, GEN pt) { GEN dyf, dxf; GEN a1 = ell_get_a1(E), a2 = ell_get_a2(E), a3 = ell_get_a3(E); GEN a4 = ell_get_a4(E); if (ell_is_inf(t)) return gen_1; dyf = gadd(gadd(gmulgs(gel(t, 2), 2),gmul(a1, gel(t, 1))), a3); if (gequal0(dyf)) return gsub(gel(pt, 1), gel(t, 1)); dxf = gsub(gmul(a1, gel(t, 2)), gadd(gadd(gmulsg(3, gsqr(gel(t, 1))), gmul(gmulsg(2, a2), gel(t, 1))), a4)); return gadd(gsub(gel(pt, 2), gel(t, 2)), gmul(gdiv(dxf, dyf), gsub(gel(pt, 1), gel(t, 1)))); } static GEN ellffchord(GEN E, GEN t, GEN s, GEN pt) { if (ell_is_inf(s)) return ellffvert(t, pt); if (ell_is_inf(t)) return ellffvert(s, pt); if (gequal(gel(s, 1), gel(t, 1))) { if (gequal(gel(s, 2), gel(t, 2))) return ellfftang(E, t, pt); else return ellffvert(t, pt); } return gsub(gsub(gel(pt, 2), gel(t, 2)), gmul(gdiv(gsub(gel(t, 2), gel(s, 2)), gsub(gel(t, 1), gel(s, 1))), gsub(gel(pt, 1), gel(t, 1)))); } struct ellff { GEN E, pt1, pt2; }; static GEN ellffadd(GEN E, GEN S, GEN T, GEN pt1, GEN pt2) { GEN s=gel(S,1), t=gel(T,1); GEN a, b, h; GEN ST = cgetg(3, t_VEC); GEN st = addell(E, s, t); pari_sp av=avma; gel(ST, 1) = st; if (ell_is_inf(st)) { a = ellffvert(s, pt1); if (gequal0(a)) return gen_0; b = ellffvert(s, pt2); } else { a = gmul(ellffchord(E, s, t, pt1), ellffvert(st, pt2)); if (gequal0(a)) return gen_0; b = gmul(ellffchord(E, s, t, pt2), ellffvert(st, pt1)); } if (gequal0(b)) return gen_0; h = gmul(gmul(gel(S,2), gel(T,2)), gdiv(a, b)); gel(ST, 2) = gerepileupto(av, h); return ST; } static GEN _ellffadd(void *data, GEN s, GEN t) { struct ellff* ff=(struct ellff*) data; if (s==gen_0 || t==gen_0) return gen_0; return ellffadd(ff->E,s,t,ff->pt1,ff->pt2); } static GEN ellffdbl(GEN E, GEN S, GEN pt1, GEN pt2) { GEN s=gel(S,1); GEN a, b, h; GEN S2 = cgetg(3, t_VEC); GEN s2 = addell(E, s, s); pari_sp av=avma; gel(S2, 1) = s2; if (ell_is_inf(s2)) { a = ellfftang(E, s, pt1); if (gequal0(a)) return gen_0; b = ellfftang(E, s, pt2); } else { a = gmul(ellfftang(E, s, pt1), ellffvert(s2, pt2)); if (gequal0(a)) return gen_0; b = gmul(ellfftang(E, s, pt2), ellffvert(s2, pt1)); } if (gequal0(b)) return gen_0; h = gmul(gsqr(gel(S,2)), gdiv(a, b)); gel(S2, 2) = gerepileupto(av, h); return S2; } static GEN _ellffdbl(void *data, GEN s) { struct ellff* ff=(struct ellff*) data; if (s==gen_0) return gen_0; return ellffdbl(ff->E, s,ff->pt1,ff->pt2); } static GEN ellffmul(GEN E, GEN t, GEN m, GEN pt1, GEN pt2) { struct ellff ff; ff.E=E; ff.pt1=pt1; ff.pt2=pt2; return gen_pow(t, m, (void*)&ff, _ellffdbl, _ellffadd); } static GEN ellweilpairing3(GEN E, GEN t, GEN s, GEN unit) { GEN t2,s2,a,b; if (gequal(s,t)) return unit; t2 = addell(E,t,t); if (gequal(s,t2)) return unit; s2 = addell(E,s,s); a = gmul(ellfftang(E, s, t), ellfftang(E, t, s2)); b = gmul(ellfftang(E, s, t2), ellfftang(E, t, s)); return gsqr(gdiv(a,b)); } GEN ellweilpairing(GEN E, GEN t, GEN s, GEN m) { pari_sp ltop=avma; GEN w, unit; checksmallell(E); checkellpt(t); checkellpt(s); if (typ(m)!=t_INT) pari_err(typeer,"ellweilpairing"); unit = gpowgs(ell_get_j(E), 0); if (ell_is_inf(s) || ell_is_inf(t)) return unit; if (equaliu(m, 2)) return gequal(s, t)?unit:gerepileupto(ltop, gneg(unit)); if (equaliu(m, 3)) return gerepileupto(ltop,ellweilpairing3(E, s, t, unit)); while(1) { GEN r, rs, tr, a, b; avma = ltop; r = ellrandom(E); rs = addell(E, r, s); tr = subell(E, t, r); if (ell_is_inf(rs) || ell_is_inf(tr) || ell_is_inf(r) || gequal(rs, t)) continue; a = ellffmul(E, mkvec2(t, gen_1), m, rs, r); if (a==gen_0) continue; b = ellffmul(E, mkvec2(s, gen_1), m, tr, invell(E,r)); if (b==gen_0) continue; if (!ell_is_inf(gel(a,1)) || !ell_is_inf(gel(b,1))) pari_err(talker,"Points of wrong order in ellweilpairing"); w = gdiv(gel(a, 2), gel(b, 2)); return gerepileupto(ltop,w); } } GEN elltatepairing(GEN E, GEN t, GEN s, GEN m) { pari_sp ltop=avma; checksmallell(E); checkellpt(t); checkellpt(s); if (typ(m)!=t_INT) pari_err(typeer,"elltatepairing"); if (ell_is_inf(s) || ell_is_inf(t)) return gen_1; while(1) { GEN r, rs, a; avma = ltop; r = ellrandom(E); rs = addell(E, r, s); if (ell_is_inf(rs) || gequal(t,r) || ell_is_inf(r) || gequal(rs, t)) continue; a = ellffmul(E, mkvec2(t, gen_1), m, rs, r); if (a==gen_0) continue; if (!ell_is_inf(gel(a,1))) pari_err(talker,"Points of wrong order in elltatepairing"); return gerepilecopy(ltop, gel(a, 2)); } } static GEN ell_to_a4a6(GEN E, GEN p) { GEN c4, c6; checkell5(E); c4 = Rg_to_Fp(ell_get_c4(E),p); c6 = Rg_to_Fp(ell_get_c6(E),p); return mkvec2(Fp_neg(Fp_mulu(c4, 27, p), p), Fp_neg(Fp_mulu(c6, 54, p), p)); } GEN ellgroup(GEN E, GEN p) { pari_sp av = avma; GEN N, N0, N1, r, F, F1, e, a4, a6; long i, j, l1; checksmallell(E); if (!p) p = get_p(E); else if (typ(p)!=t_INT) pari_err(typeer,"ellgroup"); N = subii(addis(p, 1), ellap(E, p)); r = gcdii(N, subis(p, 1)); if (is_pm1(r)) goto ellgroup_cyclic; /* Takes care of p=2 */ if (equaliu(p, 3)) { /* The only possible non-cyclic group is [2,2] which happens 9 times */ ulong b2, b4, b6; if (!equaliu(N, 4)) goto ellgroup_cyclic; /* If the group is not cyclic, T = 4x^3 + b2 x^2 + 2b4 x + b6 * must have 3 roots else 1 root. Test T(0) = T(1) = 0 mod 3 */ b6 = Rg_to_Fl(ell_get_b6(E), 3); if (b6) goto ellgroup_cyclic; /* b6 = T(0) = 0 mod 3. Test T(1) */ b2 = Rg_to_Fl(ell_get_b2(E), 3); b4 = Rg_to_Fl(ell_get_b4(E), 3); if ((1 + b2 + (b4<<1)) % 3) goto ellgroup_cyclic; return gerepileupto(av, mkvec2s(2, 2)); } /* Now assume p > 3 */ F1 = gel(Z_factor(r), 1); l1 = lg(F1); 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); if (j==1) goto ellgroup_cyclic; N0 = factorback(F); N1 = diviiexact(N, N0); e = ell_to_a4a6(E, p); a4 = gel(e, 1); a6 = gel(e, 2); while(1) { pari_sp av2 = avma; GEN P, Q, d, s, t, m, z; P = FpE_mul(random_FpE(a4,a6,p), N1, a4, p); s = FpE_order(P, F, a4, p); if (equalii(s, N0)) goto ellgroup_cyclic; Q = FpE_mul(random_FpE(a4,a6,p), N1, a4, p); t = FpE_order(Q, F, a4, p); if (equalii(t, N0)) goto ellgroup_cyclic; m = lcmii(s, t); z = FpE_weilpairing(P, Q, m, a4, p); d = Fp_order(z, F, p); /* structure is [N/d, d] iff m d == N0. Note that N/d = N1 m */ if (is_pm1(d) && equalii(m, N0)) goto ellgroup_cyclic; if (equalii(mulii(m, d), N0)) return gerepilecopy(av, mkvec2(mulii(N1,m), d)); avma = av2; } ellgroup_cyclic: return gerepileupto(av, mkveccopy(N)); } static GEN elldivpol4(GEN e, long n, long v) { GEN b2,b4,b6,b8, res; if (n==0) return pol_0(v); if (n<=2) return 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,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,gen_2,b2,gmulsg(5,b4),gmulsg(10,b6),gmulsg(10,b8),b10,b12); } setvarn(res, v); return res; } static GEN elldivpol0(GEN e, GEN t, GEN p24, 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, v); else if (n%2==1) { GEN t1 = gmul(elldivpol0(e,t,p24,m+2,v), gpowgs(elldivpol0(e,t,p24,m,v),3)); GEN t2 = gmul(elldivpol0(e,t,p24,m-1,v), gpowgs(elldivpol0(e,t,p24,m+1,v),3)); if (m%2==1) ret = gsub(t1, gmul(p24,t2)); else ret = gsub(gmul(p24,t1), t2); } else { GEN t1 = gmul(elldivpol0(e,t,p24,m+2,v), gpowgs(elldivpol0(e,t,p24,m-1,v),2)); GEN t2 = gmul(elldivpol0(e,t,p24,m-2,v), gpowgs(elldivpol0(e,t,p24,m+1,v),2)); ret = gmul(elldivpol0(e,t,p24,m,v), gsub(t1,t2)); } gel(t,n) = ret; return ret; } GEN elldivpol(GEN e, long n, long v) { pari_sp av = avma; GEN ret; checksmallell(e); if (v==-1) v = 0; if (varncmp(gvar(e), v) <= 0) pari_err(talker,"variable must have higher priority in elldivpol"); if (n<0) n = -n; if (n==1 || n==3) return gerepilecopy(av, elldivpol4(e, n, v)); else { GEN a1 = ell_get_a1(e), a2 = ell_get_a2(e), a3 = ell_get_a3(e); GEN a4 = ell_get_a4(e), a6 = ell_get_a6(e); GEN f1 = mkpoln(4, gen_1, a2, a4, a6); GEN f2 = mkpoln(2, a1, a3); GEN d2, psi24; setvarn(f1,v); setvarn(f2,v); d2 = gadd(gmulsg(4, f1), gsqr(f2)); psi24 = gsqr(d2); if (n <= 4) ret = elldivpol4(e, n, v); else { GEN t = cgetg(n+1, t_VEC); long i; for(i=1; i<=n; i++) gel(t,i) = NULL; ret = elldivpol0(e, t, psi24, n, v); } if (n%2==0) ret = gmul(ret, d2); return gerepilecopy(av, ret); } } pari-2.5.5/src/basemath/gen1.c0000644000175000017500000025717212147140046014472 0ustar billbill/* $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. */ /********************************************************************/ /** **/ /** GENERIC OPERATIONS **/ /** (first part) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" /* assume z[1] was created last */ #define fix_frac_if_int(z) if (is_pm1(gel(z,2)))\ z = gerepileupto((pari_sp)(z+3), gel(z,1)); /* assume z[1] was created last */ #define fix_frac_if_int_GC(z,tetpil) { if (is_pm1(gel(z,2)))\ z = gerepileupto((pari_sp)(z+3), gel(z,1));\ else\ gerepilecoeffssp((pari_sp)z, tetpil, z+1, 2); } static long kro_quad(GEN x, GEN y) { pari_sp av=avma; long k = kronecker(quad_disc(x), y); avma = av; return k; } /* is -1 not a square in Zp, assume p prime */ INLINE int Zp_nosquare_m1(GEN p) { return (mod4(p) & 2); /* 2 or 3 mod 4 */ } static GEN addsub_pp(GEN x, GEN y, GEN(*op)(GEN,GEN)); static GEN addsub_frac(GEN x, GEN y, GEN (*op)(GEN,GEN)); static GEN mulpp(GEN x, GEN y); static GEN divpp(GEN x, GEN y); /* Argument codes for inline routines * c: complex, p: padic, q: quad, f: floating point (REAL, some complex) * R: without imaginary part (INT, REAL, INTMOD, FRAC, PADIC if -1 not square) * T: some type (to be converted to PADIC) */ static GEN addRc(GEN x, GEN y) { GEN z = cgetg(3,t_COMPLEX); gel(z,1) = gadd(x,gel(y,1)); gel(z,2) = gcopy(gel(y,2)); return z; } static GEN mulRc(GEN x, GEN y) { GEN z = cgetg(3,t_COMPLEX); gel(z,1) = isintzero(gel(y,1))? gen_0: gmul(x,gel(y,1)); gel(z,2) = gmul(x,gel(y,2)); return z; } /* for INTMODs: can't simplify when Re(x) = gen_0 */ static GEN mulRc_direct(GEN x, GEN y) { GEN z = cgetg(3,t_COMPLEX); gel(z,1) = gmul(x,gel(y,1)); gel(z,2) = gmul(x,gel(y,2)); return z; } static GEN divRc(GEN x, GEN y) { GEN t = gdiv(x, cxnorm(y)), mt = gneg(t); /* left on stack for efficiency */ GEN z = cgetg(3,t_COMPLEX); gel(z,1) = isintzero(gel(y,1))? gen_0: gmul(t, gel(y,1)); gel(z,2) = gmul(mt, gel(y,2)); return z; } static GEN divcR(GEN x, GEN y) { GEN z = cgetg(3,t_COMPLEX); gel(z,1) = isintzero(gel(x,1))? gen_0: gdiv(gel(x,1), y); gel(z,2) = gdiv(gel(x,2), y); return z; } static GEN addRq(GEN x, GEN y) { GEN z = cgetg(4,t_QUAD); gel(z,1) = ZX_copy(gel(y,1)); gel(z,2) = gadd(x, gel(y,2)); gel(z,3) = gcopy(gel(y,3)); return z; } static GEN mulRq(GEN x, GEN y) { GEN z = cgetg(4,t_QUAD); gel(z,1) = ZX_copy(gel(y,1)); gel(z,2) = gmul(x,gel(y,2)); gel(z,3) = gmul(x,gel(y,3)); return z; } static GEN addqf(GEN x, GEN y, long prec) { pari_sp av = avma; long i = gexpo(x) - gexpo(y); if (i > 0) prec += divsBIL( i ); return gerepileupto(av, gadd(y, quadtofp(x, prec))); } 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(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 */ /* better than nothing */ pari_err(talker,"%Ps is not invertible in gred_rfrac()", y); } 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(gdiver); return scalarpol(gdiv(n, gel(d,2)), varn(d)); } 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) = gcopy(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) = gcopy(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(talker,"incompatible variables in gred"); } 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 || varn(x) != varn(y) || degpol(x) <= 0) return gcopy(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: 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) = gcopy(X); gel(T,1) = Y; gel(T,2) = y; y = T; } else { gel(z,1) = gcopy(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) = gcopy(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(operi,"+",x,y); return RgV_add(x,y); case t_COL: if (lg(y) != lg(x)) pari_err(operi,"+",x,y); return RgC_add(x,y); case t_MAT: lx = lg(x); if (lg(y) != lx) pari_err(operi,"+",x,y); if (lx == 1) return cgetg(1, t_MAT); if (lg(y[1]) != lg(x[1])) pari_err(operi,"+",x,y); return RgM_add(x,y); default: pari_err(operf,"+",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(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(operf,"+",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(operi,"+",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(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(operf,"+",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(operi,"+",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(operf,"+",x,y); if (isrationalzero(x)) return gcopy(y); return RgM_Rg_add(y, x); case t_COL: if (tx == t_VEC) pari_err(operf,"+",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(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(operf,"+",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(operf,"+",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), lx, vx, vy; pari_sp av; GEN z, p1; 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 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, remii(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(operi,"+",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(operi,"+",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: vx = varn(x); 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(operi,"+",x,y); return RgV_sub(x,y); case t_COL: if (lg(y) != lg(x)) pari_err(operi,"+",x,y); return RgC_sub(x,y); case t_MAT: lx = lg(x); if (lg(y) != lx) pari_err(operi,"+",x,y); if (lx == 1) return cgetg(1, t_MAT); if (lg(y[1]) != lg(x[1])) pari_err(operi,"+",x,y); return RgM_sub(x,y); case t_RFRAC: case t_SER: break; default: pari_err(operf,"+",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_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) z = gred_rfrac_simple(gmul(gel(z,1), n), gel(z,2)); else z = gmul(z, n); return gerepileupto(av, z); } static GEN mul_scal(GEN y, GEN x, long ty) { switch(ty) { case t_POL: 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(operf,"*",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 */ static GEN div_rfrac_pol(GEN x1, GEN x2, GEN y2) { GEN z, X; pari_sp av = avma; X = gred_rfrac2_i(x1, y2); if (typ(X) == t_RFRAC) z = gred_rfrac_simple(gel(X,1), gmul(gel(X,2),x2)); else z = mul_gen_rfrac(X, mkrfrac(gen_1, x2)); return gerepileupto(av, z); } /* 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) = gcopy(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) = gcopy(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) = gcopy(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); pari_sp av; if (vx==vy) { 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) = gcopy(X); gel(T,1) = Y; gel(T,2) = y; y = T; } else { gel(z,1) = gcopy(Y); gel(T,1) = X; gel(T,2) = x; x = T; } gel(z,2) = gmul(x, y); return z; } /* 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(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(x[1]) == -signe(y)) { *z = gsub(x,y); return 0; } else { *z = gadd(x,y); return 1; } } *z = gadd(x,y); return 1; } /* 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; /* 3M method avoiding catastrophic cancellation */ 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); if (isintzero(gel(z,2))) { cgiv(gel(z,2)); return gerepileupto((pari_sp)(z+3), gel(z,1)); } 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(operi,"*",x,y); if (!signe(x[4])) return zeropadic(gel(x,2), l); if (!signe(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(operi,"*",x,y); gel(z,1) = gcopy(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); } } GEN gmul(GEN x, GEN y) { long tx, ty, lx, ly, vx, vy, i, j, 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: { long mix, miy; 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); if (lx > lg(y)) { lx = lg(y); 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); if (lx > 200) /* threshold for 32bit coeffs: 400, 512 bits: 100 */ { long ly; y = RgX_mul(ser2pol_i(x, lx), ser2pol_i(y, lx)); ly = lg(y); if (ly >= lx) { for (i = 2; i < lx; i++) z[i] = y[i]; } else { for (i = 2; i < ly; i++) z[i] = y[i]; for ( ; i < lx; i++) gel(z,i) = gen_0; } z = normalize(z); return gerepilecopy((pari_sp)(z + lx), z); } x += 2; y += 2; z += 2; lx -= 3; p2 = (GEN)pari_malloc((lx+1)*sizeof(long)); mix = miy = 0; for (i=0; i<=lx; i++) { p2[i] = !isrationalzero(gel(y,i)); if (p2[i]) miy = i; if (!isrationalzero(gel(x,i))) mix = i; p1 = gen_0; av = avma; for (j=i-mix; j<=minss(i,miy); j++) if (p2[j]) p1 = gadd(p1, gmul(gel(y,j),gel(x,i-j))); gel(z,i) = gerepileupto(av,p1); } z -= 2; /* back to normalcy */ pari_free(p2); return normalize(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(operf,"*",x,y); z[i] = x[yi]; } return z; default: pari_err(operf,"*",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: if (!signe(y[1])) return gen_0; av = avma; return gerepileuptoleaf(av, divri(mulri(x,gel(y,1)), gel(y,2))); case t_COMPLEX: return mulRc(x, y); case t_QUAD: return mulqf(y, x, lg(x)); default: pari_err(operf,"*",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(operi,"*",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(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(operf,"*",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(operi,"*",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(operf, "*",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(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(operf,"*",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 = mod_to_Kronecker(P, 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, l; 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(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) = gcopy(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: return normalize( sqr_ser_part(x, 0, lg(x)-3) ); 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, &l); for (i=1; i= l) pari_err(operf,"*",x,x); z[i] = x[xi]; } return z; } pari_err(operf,"*",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) && degpol(y1) > 0) return gerepileupto(av, gred_rfrac_simple(gmul(x, y2), y1)); 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(gdiver); } 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) = gcopy(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(gdiver); 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(operi,"/",x,y); return divpp(x, y); case t_QUAD: if (!ZX_equal(gel(x,1),gel(y,1))) pari_err(operi,"/",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(gdiver); 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; y = RgM_inv(y); if (!y) pari_err(matinv1); return gerepileupto(av, RgM_mul(x, y)); default: pari_err(operf,"/",x,y); } if (tx==t_INT && is_const_t(ty)) /* optimized for speed */ { long s = signe(x); if (!s) { if (gequal0(y)) pari_err(gdiver); 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(gdiver); 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(operf,"/",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(operi,"/",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(operf,"/",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(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(operi,"/",x,y); return FF_Z_Z_muldiv(x,gen_1,gel(y,2)); default: pari_err(operf,"/",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(operi,"/",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(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(operf,"/",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(operi,"/",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; y = RgM_inv(y); if (!y) pari_err(matinv1); return gerepileupto(av, gmul(x, y)); case t_VEC: case t_COL: case t_LIST: case t_STR: case t_VECSMALL: case t_CLOSURE: pari_err(operf,"/",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) = gcopy(X); gel(z,2) = gdiv(gel(x,2), y); return z; } /* y is POL, SER or RFRAC */ av = avma; 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(operf,"/",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) = gcopy(gel(y,1)); gel(z,2) = gmulsg(s,gel(y,2)); return z; case t_POL: if (!s || !signe(y)) return zeropol(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) = gcopy(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; 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) */ y = gadd(x, gmul(x, gsubsg(1, gmul(a,x)))); 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) = gcopy(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(gdiver); 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(x[4])) pari_err(gdiver); 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(gdiver); n = simplify_shallow(n); if (typ(n) != t_POL || varn(n) != varn(d)) { if (gequal1(n)) { avma = av; return gcopy(d); } ltop = avma; z = RgX_Rg_div(d,n); } else { ltop = avma; z = cgetg(3,t_RFRAC); gel(z,1) = gcopy(d); gel(z,2) = gcopy(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: y = RgM_inv(x); if (!y) pari_err(matinv1); return y; case t_VECSMALL: { long i, lx = lg(x)-1; y = const_vecsmall(lx,0); for (i=1; i<=lx; i++) { long xi = x[i]; if (xi<1 || xi>lx || y[xi]) pari_err(talker,"incorrect permutation to inverse"); y[xi] = i; } return y; } } pari_err(typeer,"inverse"); return NULL; /* not reached */ } pari-2.5.5/src/basemath/bibli1.c0000644000175000017500000017302012147140046014767 0ustar billbill/* $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. */ /********************************************************************/ /** **/ /** 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 || lg(x) > 3 || expo(x) < BITS_IN_LONG/2); } /* zero x[1..k-1], 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 30) { long e; q = grndtoi(q, &e); if (e > 0) return NULL; } else q = ground(q); return q; } GEN gram_matrix(GEN x) { long i,j, lx = lg(x), tx = typ(x); GEN g; if (!is_matvec_t(tx)) pari_err(typeer,"gram"); g = cgetg(lx,t_MAT); for (i=1; i= |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 = gtodouble(glog(B, DEFAULTPREC)) / logN; if (tau >= beta * beta / d) pari_err(talker, "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 GEN do_exhaustive(GEN P, GEN N, long x, GEN B) { GEN tst, sol = vecsmalltrunc_init(2*x + 2); long j, l; for (j = -x; j <= x; j++) { tst = gcdii(FpX_eval(P, stoi(j), N), N); if (cmpii(tst, B) >= 0) /* We have found a factor of N >= B */ { for (l = 1; l < lg(sol) && j != sol[l]; l++) /*empty*/; if (l == lg(sol)) vecsmalltrunc_append(sol, j); } } return zv_to_ZV(sol); } /* General Coppersmith, look for a root x0 <= p, p >= B, p | N, |x0| <= X */ GEN zncoppersmith(GEN P0, GEN N, GEN X, GEN B) { GEN Q, R, N0, M, sh, short_pol, *Xpowers, z, r, sol, nsp, P, tst, 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 || typ(N) != t_INT) pari_err(typeer, "zncoppersmith"); if (typ(X) != t_INT) { X = gfloor(X); if (typ(X) != t_INT) pari_err(typeer, "zncoppersmith"); } if (signe(X) < 0) pari_err(talker, "negative bound in zncoppersmith"); if (!B) B = N; if (typ(B) != t_INT) B = gceil(B); if (cmpiu(X, X_SMALL) <= 0) return gerepileupto(av, do_exhaustive(P0, N, itos(X), B)); /* bnd-hack is only for the case B = N */ if (!equalii(B,N)) bnd = 1; P = leafcopy(P0); d = degpol(P); if (d == 0) { avma = av; return cgetg(1, t_VEC); } if (d < 0) pari_err(talker, "zero polynomial forbidden"); if (!gequal1(gel(P,d+2))) { 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 != N) 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(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++) { r = nfrootsQ(R); if (DEBUGLEVEL >= 2) err_printf("Roots: %Ps\n", r); for (j = 1; j < lg(r); j++) { z = gel(r,j); tst = gcdii(FpX_eval(P, z, N), N); if (cmpii(tst, B) >= 0) /* We have found a factor of N >= B */ { for (l = 1; l < lg(sol) && !equalii(z, gel(sol,l)); l++) /*empty*/; if (l == lg(sol)) sol = shallowconcat(sol, z); } } if (i < bnd) gel(R,2) = addii(gel(R,2), Z); } return gerepilecopy(av, 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(typeer,"lindep2"); if (lx<=2) return cgetg(1,t_COL); if (bit < 0) pari_err(talker, "negative accuracy in lindep2"); if (!bit) { bit = gprecision(x); if (!bit) { x = primpart(x); bit = 32 + gexpo(x); } else bit = (long)bit_accuracy_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 -10) pari_err(precer,"lindep"); qzer = cgetg(lx, t_VECSMALL); b = matid(n); be = cgetg(lx, t_MAT); bn = cgetg(lx, t_COL); m = cgetg(lx, t_VEC); /* vector of columns of increasing length */ for (i=1; i<=n; i++) { GEN cb = cgetg(lx,t_COL), cm = cgetg(i, t_COL); gel(bn,i) = cgetr(prec+1); gel(be,i) = cb; gel(m,i) = cm; for (j=1; j 0) { em = u; j = i; } } i = j; k = i+1; avma = av1; r = grndtoi(gmael(m,k,i), &e); if (e >= 0) pari_err(precer,"lindep"); togglesign_safe(&r); ZC_lincomb1_inplace(gel(b,k), gel(b,i), r); swap(gel(b,k), gel(b,i)); av1 = avma; f = addir(r, gmael(m,k,i)); for (j=1; j1) pari_warn(warnmem,"lindep"); b = gerepilecopy(av0, b); av1 = avma; } } return gerepileupto(av, RgM_solve(shallowtrans(b), col_ei(n,n))); } /* PSLQ Programs */ typedef struct { long vmind, t12, t1234, reda, fin; long ct; pari_timer t; } pslq_timer; /* WARNING: for double ** matrices, A[i] is the i-th ROW of A */ typedef struct { double *y, **H, **A, **B; double *W; /* scratch space */ long n; pslq_timer *T; } pslqL2_M; typedef struct { GEN y, H, A, B; long n, EXP; int flreal; pslq_timer *T; } pslq_M; void init_dalloc(void) { /* correct alignment for dalloc */ (void)new_chunk((avma % sizeof(double)) / sizeof(long)); } double * dalloc(size_t n) { return (double*)new_chunk(n / sizeof(long)); } char * stackmalloc(size_t N) { long n = nchar2nlong(N); return (char*)new_chunk(n); } static double conjd(double x) { return x; } static double sqrd(double a) { return a*a; } static void redall(pslq_M *M, long i, long jsup) { long j, k, n = M->n; GEN t,b; GEN A = M->A, B = M->B, H = M->H, y = M->y; const GEN Bi = gel(B,i); for (j=jsup; j>=1; j--) { pari_sp av = avma; t = round_safe( gdiv(gcoeff(H,i,j), gcoeff(H,j,j)) ); if (!t || gequal0(t)) { avma = av; continue; } b = gel(B,j); gel(y,j) = gadd(gel(y,j), gmul(t,gel(y,i))); for (k=1; k<=j; k++) gcoeff(H,i,k) = gsub(gcoeff(H,i,k), gmul(t,gcoeff(H,j,k))); for (k=1; k<=n; k++) { gcoeff(A,i,k) = gsub(gcoeff(A,i,k), gmul(t,gcoeff(A,j,k))); gel(b,k) = gadd(gel(b,k), gmul(t,gel(Bi,k))); } } } static void redallbar(pslqL2_M *Mbar, long i, long jsup) { long j, k, n = Mbar->n; double t; double *hi = Mbar->H[i], *ai = Mbar->A[i], *hj, *aj; #ifdef DEBUGPSLQ err_printf("%ld:\n==\n",i); #endif for (j=jsup; j>=1; j--) { hj = Mbar->H[j]; t = floor(0.5 + hi[j] / hj[j]); if (!t) continue; #ifdef DEBUGPSLQ err_printf("%15.15e ",t); #endif aj = Mbar->A[j]; Mbar->y[j] += t * Mbar->y[i]; for (k=1; k<=j; k++) hi[k] -= t * hj[k]; for (k=1; k<=n; k++) { ai[k] -= t * aj[k]; Mbar->B[k][j] += t * Mbar->B[k][i]; } #ifdef DEBUGPSLQ err_printf(" %ld:\n",j); dprintmat(Mbar->H,n,n-1); #endif } } static long vecabsminind(GEN v) { long l = lg(v), m = 1, i; GEN t, la = mpabs(gel(v,1)); for (i=2; i 0) { la = t; m = i; } } return m; } static long vecmaxindbar(double *v, long n) { long m = 1, i; double la = v[1]; for (i=2; i<=n; i++) if (v[i] > la) { la = v[i]; m = i; } return m; } static GEN maxnorml2(pslq_M *M) { long n = M->n, i, j; GEN ma = gen_0, s; for (i=1; i<=n; i++) { s = gen_0; for (j=1; jH,i,j))); if (gcmp(ma,s) < 0) ma = s; } return sqrtr(gtofp(ma, DEFAULTPREC)); } static void init_timer(pslq_timer *T) { T->vmind = T->t12 = T->t1234 = T->reda = T->fin = T->ct = 0; timer_start(&T->t); } static int is_zero(GEN x, long e, long prec) { if (gequal0(x)) return 1; if (typ(x) == t_REAL) { long ex = expo(x); return (ex < e || (prec != 3 && lg(x) == 3 && ex < (e>>1))); } return gexpo(x) < e; } static GEN init_pslq(pslq_M *M, GEN x, long *PREC) { long tx = typ(x), lx = lg(x), n = lx-1, i, j, k, prec; GEN s1, s, sinv; if (! is_vec_t(tx)) pari_err(typeer,"pslq"); /* check trivial cases */ for (k = 1; k <= n; k++) if (gequal0(gel(x,k))) return col_ei(n, k); if (n <= 1) return cgetg(1, t_COL); prec = gprecision(x) - 1; /* don't trust the last word */ if (prec < 0) { /* exact components */ pari_sp av = avma; GEN im, U = NULL; x = Q_primpart(x); im = imag_i(x); x = real_i(x); settyp(x, t_VEC); if (!gequal0(im)) { U = gel(extendedgcd(im),2); setlg(U, lg(U)-1); /* remove last column */ x = gmul(x, U); if (n == 2) /* x has a single component */ return gequal0(gel(x,1))? gel(U,1): cgetg(1, t_COL); } x = gel(extendedgcd(x),2); x = gel(x,1); if (U) x = gmul(U, x); return gerepilecopy(av, x); } if (prec < DEFAULTPREC) prec = DEFAULTPREC; *PREC = prec; M->EXP = - bit_accuracy(prec) + maxss(n, 8); M->flreal = is_zero(imag_i(x), M->EXP, prec); if (!M->flreal) return lindep(x); /* FIXME */ else x = real_i(x); if (DEBUGLEVEL>=3) init_timer(M->T); x = RgC_gtofp(x, prec); settyp(x,t_VEC); M->n = n; M->A = matid(n); M->B = matid(n); s1 = cgetg(lx,t_VEC); gel(s1,n) = gnorm(gel(x,n)); s = cgetg(lx,t_VEC); gel(s,n) = gabs(gel(x,n),prec); for (k=n-1; k>=1; k--) { gel(s1,k) = gadd(gel(s1,k+1), gnorm(gel(x,k))); gel(s,k) = gsqrt(gel(s1,k), prec); } sinv = ginv(gel(s,1)); s = gmul(sinv,s); M->y = gmul(sinv, x); M->H = cgetg(n,t_MAT); for (j=1; jH,j) = c; for (i=1; iy,j), gmul(gel(s,j),gel(s,j+1)) )); for (i=j+1; i<=n; i++) gel(c,i) = gmul(gconj(gel(M->y,i)), d); } for (i=2; i<=n; i++) redall(M, i, i-1); return NULL; } static void SWAP(pslq_M *M, long m) { long j, n = M->n; swap(gel(M->y,m), gel(M->y,m+1)); swap(gel(M->B,m), gel(M->B,m+1)); for (j=1; j<=n; j++) swap(gcoeff(M->A,m,j), gcoeff(M->A,m+1,j)); for (j=1; jH,m,j), gcoeff(M->H,m+1,j)); } static void SWAPbar(pslqL2_M *M, long m) { long j, n = M->n; dswap(M->y[m], M->y[m+1]); pdswap(M->A[m], M->A[m+1]); pdswap(M->H[m], M->H[m+1]); for (j=1; j<=n; j++) dswap(M->B[j][m], M->B[j][m+1]); } static GEN one_step_gen(pslq_M *M, GEN tabga, long prec) { GEN H = M->H, p1; long n = M->n, i, m; p1 = cgetg(n,t_VEC); for (i=1; i3) M->T->vmind += timer_delay(&M->T->t); SWAP(M, m); if (m <= n-2) { GEN tinv, t3, t4, t1c, t2c, t1 = gcoeff(H,m,m), t2 = gcoeff(H,m,m+1); tinv = ginv( gsqrt(gadd(gnorm(t1), gnorm(t2)), prec) ); t1 = gmul(t1, tinv); t2 = gmul(t2, tinv); if (M->flreal) { t1c = t1; t2c = t2; } else { t1c = gconj(t1); t2c = gconj(t2); } if (DEBUGLEVEL>3) M->T->t12 += timer_delay(&M->T->t); for (i=m; i<=n; i++) { t3 = gcoeff(H,i,m); t4 = gcoeff(H,i,m+1); gcoeff(H,i,m) = gadd(gmul(t1c,t3), gmul(t2c,t4)); gcoeff(H,i,m+1) = gsub(gmul(t1, t4), gmul(t2, t3)); } if (DEBUGLEVEL>3) M->T->t1234 += timer_delay(&M->T->t); } for (i=1; iEXP, prec)) { m = vecabsminind(M->y); return gel(M->B,m); } for (i=m+1; i<=n; i++) redall(M, i, minss(i-1,m+1)); if (DEBUGLEVEL>3) M->T->reda += timer_delay(&M->T->t); if (gexpo(M->A) >= -M->EXP) return ginv(maxnorml2(M)); m = vecabsminind(M->y); if (is_zero(gel(M->y,m), M->EXP, prec) && gexpo(M->y) - gexpo(gel(M->y,m)) > 20) return gel(M->B,m); if (DEBUGLEVEL>2) { if (DEBUGLEVEL>3) M->T->fin += timer_delay(&M->T->t); M->T->ct++; if ((M->T->ct&0xff) == 0) { if (DEBUGLEVEL == 3) err_printf("time for ct = %ld : %ld\n",M->T->ct, timer_delay(&M->T->t)); else err_printf("time [max,t12,loop,reds,fin] = [%ld, %ld, %ld, %ld, %ld]\n", M->T->vmind, M->T->t12, M->T->t1234, M->T->reda, M->T->fin); } } return NULL; /* nothing interesting */ } static GEN get_tabga(int flreal, long n, long prec) { GEN ga = sqrtr( flreal? divru(stor(4, prec), 3): stor(2, prec) ); GEN tabga = cgetg(n,t_VEC); long i; gel(tabga,1) = ga; for (i = 2; i < n; i++) gel(tabga,i) = gmul(gel(tabga,i-1),ga); return tabga; } GEN pslq(GEN x) { GEN tabga, p1; long prec; pari_sp av0 = avma, lim = stack_lim(av0,1), av; pslq_M M; pslq_timer T; M.T = &T; p1 = init_pslq(&M, x, &prec); if (p1) return p1; tabga = get_tabga(M.flreal, M.n, prec); av = avma; if (DEBUGLEVEL>=3) timer_printf(&M.T->t, "Initialization"); for (;;) { if ((p1 = one_step_gen(&M, tabga, prec))) return gerepilecopy(av0, p1); if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"pslq"); gerepileall(av,4,&M.y,&M.H,&M.A,&M.B); } } } /* W de longueur n-1 */ static double dnorml2(double *W, long n, long row) { long i; double s = 0.; for (i=row; in; /* > row */ long i, j, k; double s, *W = Mbar->W, **H = Mbar->H; for (i = row; i <= n; i++) { for (j = row; j < n; j++) { k = row; s = H[i][k] * Pbar[k][j]; for ( ; k < n; k++) s += H[i][k] * Pbar[k][j]; W[j] = s; } for (j = row; j < n; j++) H[i][j] = W[j]; } } /* compute n-1 x n-1 matrix Pbar */ static void dmakep(pslqL2_M *Mbar, double **Pbar, long row) { long i, j, n = Mbar->n; double pro, nc, *C = Mbar->H[row], *W = Mbar->W; nc = sqrt(dnorml2(C,n,row)); W[row] = (C[row] < 0) ? C[row] - nc : C[row] + nc; for (i=row; in; for (row=1; rowH[row][j] = 0.; } } #ifdef DEBUGPSLQ static void dprintvec(double *V, long m) { long i; err_printf("["); for (i=1; in; GEN ypro; pari_sp av = avma; ypro = gdiv(M->y, vecmax(gabs(M->y,prec))); for (i=1; i<=n; i++) { if (gexpo(gel(ypro,i)) < -0x3ff) return 0; Mbar->y[i] = rtodbl(gel(ypro,i)); } avma = av; for (j=1; j<=n; j++) for (i=1; i<=n; i++) { if (i==j) Mbar->A[i][j] = Mbar->B[i][j] = 1.; else Mbar->A[i][j] = Mbar->B[i][j] = 0.; if (j < n) { GEN h = gcoeff(M->H,i,j); if (!gequal0(h) && labs(gexpo(h)) > 0x3ff) return 0; Mbar->H[i][j] = rtodbl(h); } } return 1; } /* T(arget) := S(ource) */ static void storeprecdoubles(pslqL2_M *T, pslqL2_M *S) { long n = T->n, i, j; for (i=1; i<=n; i++) { for (j=1; jH[i][j] = S->H[i][j]; T->A[i][j] = S->A[i][j]; T->B[i][j] = S->B[i][j]; } T->A[i][n] = S->A[i][n]; T->B[i][n] = S->B[i][n]; T->y[i] = S->y[i]; } } static long checkentries(pslqL2_M *Mbar) { long n = Mbar->n, i, j; double *p1, *p2; for (i=1; i<=n; i++) { if (dblexpo(Mbar->y[i]) < -46) return 0; p1 = Mbar->A[i]; p2 = Mbar->B[i]; for (j=1; j<=n; j++) if (dblexpo(p1[j]) > 43 || dblexpo(p2[j]) > 43) return 0; } return 1; } static long applybar(pslq_M *M, pslqL2_M *Mbar, GEN Abargen, GEN Bbargen) { long n = Mbar->n, i, j; double *p1, *p2; for (i=1; i<=n; i++) { p1 = Mbar->A[i]; p2 = Mbar->B[i]; for (j=1; j<=n; j++) { if (dblexpo(p1[j]) >= 52 || dblexpo(p2[j]) >= 52) return 0; gcoeff(Abargen,i,j) = stoi((long)floor(p1[j])); gcoeff(Bbargen,i,j) = stoi((long)floor(p2[j])); } } M->y = gmul(M->y, Bbargen); M->B = gmul(M->B, Bbargen); M->A = gmul(Abargen, M->A); M->H = gmul(Abargen, M->H); return 1; } static GEN checkend(pslq_M *M, long prec) { long i, m, n = M->n; for (i=1; i<=n-1; i++) if (is_zero(gcoeff(M->H,i,i), M->EXP, prec)) { m = vecabsminind(M->y); return gel(M->B,m); } if (gexpo(M->A) >= -M->EXP) return ginv( maxnorml2(M) ); m = vecabsminind(M->y); if (is_zero(gel(M->y,m), M->EXP, prec)) return gel(M->B,m); return NULL; } GEN pslqL2(GEN x) { GEN Abargen, Bbargen, tabga, p1; long lx = lg(x), n = lx-1, i, m, ctpro, flreal, flit, prec; pari_sp av0 = avma, lim = stack_lim(av0,1), av; double *tabgabar, gabar, tinvbar, t1bar, t2bar, t3bar, t4bar; double **Pbar, **Abar, **Bbar, **Hbar; pslqL2_M Mbar, Mbarst; pslq_M M; pslq_timer T; M.T = &T; p1 = init_pslq(&M, x, &prec); if (p1) return p1; flreal = M.flreal; tabga = get_tabga(flreal, n, prec); Abargen = matid(n); Bbargen = matid(n); Mbarst.n = Mbar.n = n; Mbar.A = Abar = (double**)new_chunk(n+1); Mbar.B = Bbar = (double**)new_chunk(n+1); Mbar.H = Hbar = (double**)new_chunk(n+1); Mbarst.A = (double**)new_chunk(n+1); Mbarst.B = (double**)new_chunk(n+1); Mbarst.H = (double**)new_chunk(n+1); Pbar = (double**)new_chunk(n); tabgabar = dalloc((n+1)*sizeof(double)); Mbar.y = dalloc((n+1)*sizeof(double)); Mbarst.y = dalloc((n+1)*sizeof(double)); Mbar.W = dalloc((n+1)*sizeof(double)); for (i=1; i< n; i++) Pbar[i] = dalloc((n+1)*sizeof(double)); for (i=1; i<=n; i++) Abar[i] = dalloc((n+1)*sizeof(double)); for (i=1; i<=n; i++) Bbar[i] = dalloc((n+1)*sizeof(double)); for (i=1; i<=n; i++) Hbar[i] = dalloc(n*sizeof(double)); for (i=1; i<=n; i++) Mbarst.A[i] = dalloc((n+1)*sizeof(double)); for (i=1; i<=n; i++) Mbarst.B[i] = dalloc((n+1)*sizeof(double)); for (i=1; i<=n; i++) Mbarst.H[i] = dalloc(n*sizeof(double)); gabar = gtodouble(gel(tabga,1)); tabgabar[1] = gabar; for (i=2; i=3) timer_printf(&M.T->t, "Initialization"); RESTART: flit = initializedoubles(&Mbar, &M, prec); storeprecdoubles(&Mbarst, &Mbar); if (flit) dLQdec(&Mbar, Pbar); ctpro = 0; for (;;) { if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"pslq"); gerepileall(av,4,&M.y,&M.H,&M.A,&M.B); } if (flit) { ctpro++; for (i=1; i=4) T.t12 += timer_delay(&M.T->t); for (i=m; i<=n; i++) { t3bar = Hbar[i][m]; t4bar = Hbar[i][m+1]; if (flreal) Hbar[i][m] = t1bar*t3bar + t2bar*t4bar; else Hbar[i][m] = conjd(t1bar)*t3bar + conjd(t2bar)*t4bar; Hbar[i][m+1] = t1bar*t4bar - t2bar*t3bar; } if (DEBUGLEVEL>=4) T.t1234 += timer_delay(&M.T->t); } flit = checkentries(&Mbar); if (flit) { storeprecdoubles(&Mbarst, &Mbar); for (i=m+1; i<=n; i++) redallbar(&Mbar, i, minss(i-1,m+1)); } else { if (applybar(&M, &Mbar, Abargen,Bbargen)) { if ( (p1 = checkend(&M, prec)) ) return gerepilecopy(av0, p1); goto RESTART; } else { if (ctpro == 1) goto DOGEN; storeprecdoubles(&Mbar, &Mbarst); /* restore */ if (! applybar(&M, &Mbar, Abargen,Bbargen)) pari_err(bugparier,"pslqL2"); if ( (p1 = checkend(&M, prec)) ) return gerepilecopy(av0, p1); goto RESTART; } } } else { DOGEN: if ((p1 = one_step_gen(&M, tabga, prec))) return gerepilecopy(av, p1); } } } /* x is a vector of elts of a p-adic field */ GEN plindep(GEN x) { long i, j, prec = LONG_MAX, nx = lg(x)-1, v; pari_sp av = avma; GEN p = NULL, pn,p1,m,a; if (nx < 2) return cgetg(1,t_COL); for (i=1; i<=nx; i++) { p1 = gel(x,i); if (typ(p1) != t_PADIC) continue; j = precp(p1); if (j < prec) prec = j; if (!p) p = gel(p1,2); else if (!equalii(p, gel(p1,2))) pari_err(talker,"inconsistent primes in plindep"); } if (!p) pari_err(talker,"not a p-adic vector in plindep"); v = ggval(x,p); pn = powiu(p,prec); if (v != 0) x = gmul(x, powis(p, -v)); x = RgV_to_FpV(x, pn); a = negi(gel(x,1)); m = cgetg(nx,t_MAT); 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 = plindep(y); else { y = lindep0(y, bit); if (typ(y) == t_REAL) return gerepileupto(av, y); } if (lg(y) < 2) pari_err(talker,"higher degree than expected in algdep"); y = RgV_to_RgX(y, 0); if (gsigne(leading_term(y)) > 0) return gerepilecopy(av, y); return gerepileupto(av, RgX_neg(y)); } GEN algdep(GEN x, long n) { return algdep0(x,n,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 (k> 1; L = const_vecsmall(maxrank, 0); 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]); if (flag == min_PERF) invp = matid(maxrank); 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 (flag == min_FIRST) { gel(res,2) = gerepileupto(av, ZM_zc_mul(u,x)); av = avma; gel(res,1) = gerepileuptoint(av, roundr(dbltor(p))); return res; } if (p > maxnorm) maxnorm = p; } else { pari_sp av2 = avma; gnorme = roundr(dbltor(p)); if (cmpii(gnorme,BORNE) >= 0) avma = av2; else { BOUND=gtodouble(gnorme)*(1+eps); s=0; affii(gnorme,BORNE); avma = av1; } } s++; switch(flag) { 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); res[norm]++; } break; case min_VECSMALL2: { ulong norm = (ulong)(p + 0.5); if ((norm&1) == 0) res[norm>>1]++; } break; case min_PERF: { long I=1; pari_sp av2; 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=av0; return cgetg(1,t_VEC); case min_VECSMALL: case min_VECSMALL2: avma=av; return res; case min_PERF: if (DEBUGLEVEL>1) { err_printf("\n"); err_flush(); } avma=av0; return stoi(s); } k = minss(s,maxrank); r = (maxnorm >= 0) ? roundr(dbltor(maxnorm)): BORNE; L[0] = evaltyp(t_MAT) | evallg(k + 1); for (j=1; j<=k; j++) gel(L,j) = ZM_zc_mul(u, gel(L,j)); gerepileall(av, 2, &r, &L); gel(res,1) = stoi(s<<1); gel(res,2) = r; gel(res,3) = L; return res; } GEN qfrep0(GEN a, GEN borne, long flag) { pari_sp av = avma; GEN g = minim0(a, borne, gen_0, (flag & 1)? min_VECSMALL2: min_VECSMALL); if ((flag & 2) == 0) g = gerepileupto(av, gtovec(g)); return g; } 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(typeer,"qfminim"); if (stockmax) { if (typ(stockmax) != t_INT) pari_err(typeer,"qfminim"); maxnum = itos(stockmax); } a = fincke_pohst(a,borne,maxnum,prec,NULL); if (!a) pari_err(precer,"qfminim"); return a; } default: pari_err(flagerr,"qfminim"); } return NULL; /* not reached */ } GEN minim(GEN a, GEN borne, GEN stockmax) { return minim0(a,borne,stockmax,min_ALL); } GEN minim2(GEN a, GEN borne, GEN stockmax) { return minim0(a,borne,stockmax,min_FIRST); } GEN perf(GEN a) { return minim0(a,gen_0,gen_0,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; } INLINE void step(GEN x, GEN y, GEN inc, long k) { if (!signe(y[k])) gel(x,k) = addis(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; } } /* 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 < borne1, approximately */ static int check_bound(GEN borne1, GEN xk, GEN yk, GEN zk, GEN vk) { pari_sp av = avma; long i; GEN t = mpadd(xk, zk); if (!isintzero(t)) yk = mpadd(yk, mpmul(vk, mpsqr(t))); i = mpcmp(yk, borne1); avma = av; return (i <= 0); } static GEN add_fudge(GEN x) { if (typ(x) == t_INT) return addir(x, real2n(-32,3)); if (!signe(x)) return x; return addrr(x, real2n(expo(x) - (bit_accuracy(lg(x)) >> 1), 3)); } static GEN sub_fudge(GEN x) { if (typ(x) == t_INT) return subir(x, real2n(-32,3)); if (!signe(x)) return x; return subrr(x, real2n(expo(x) - (bit_accuracy(lg(x)) >> 1), 3)); } /* q is the Gauss reduction of the quadratic form */ /* general program for positive definit quadratic forms (real coeffs). * Enumerate vectors whose norm is less than BORNE, 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; if (check) norms = cgetg(stockmax+1,t_VEC); 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 */ { do { int fl = 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,check?7:6,&x,&y,&z,&normax1,&borne1,&borne2,&norms); } } while (k > 1); if (!signe(x[1]) && !signe(y[1])) continue; /* exclude 0 */ av1 = avma; p1 = mpsqr(mpadd(gel(x,1),gel(z,1))); norme1 = mpadd(gel(y,1), mpmul(p1, gel(v,1))); if (mpcmp(norme1,borne1) > 0) { avma=av1; continue; /* main */ } norme1 = gerepileupto(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 = add_fudge(norme1); borne2 = mulrr(borne1, alpha); s = 0; checkcnt = 0; } } else { if (!BORNE) /* find minimal vectors */ { if (mpcmp(norme1, borne2) < 0) { borne1 = add_fudge(norme1); borne2 = sub_fudge(norme1); s = 0; } } else if (mpcmp(norme1,normax1) > 0) normax1 = norme1; } if (++s <= stockmax) { if (check) gel(norms,s) = norme1; gel(S,s) = leafcopy(x); if (s != stockmax) continue; /* overflow */ 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))) { norme1 = gel(norms,k); borne1 = add_fudge(norme1); break; } } imin = i; for (; i <= s; i++) if (mpcmp(gel(norms,per[i]), borne1) > 0) break; imax = i; for (i=imin, s=0; i < imax; i++) gel(S,++s) = gel(S,per[i]); avma = av2; if (s) { borne1 = add_fudge(norme1); borne2 = mulrr(borne1, alpha); checkcnt = 0; } if (!stockall) continue; if (s > stockmax/2) stockmax <<= 1; } 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; } norms = cgetg(stockmax+1, t_VEC); for (i = 1; i <= s; i++) gel(norms,i) = norme1; } } 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]; norme1 = gel(norms,t); if (j && mpcmp(norme1, borne1) > 0) break; if ((p = check(data,gel(S,t)))) { if (!j) borne1 = add_fudge(norme1); j++; gel(pols,j) = p; alph[j]=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(talker, "dimension 0 in fincke_pohst"); z = cgetg(4,t_VEC); gel(z,1) = gel(z,2) = gen_0; gel(z,3) = cgetg(1,t_MAT); return z; } i = gprecision(a); if (i) prec = i; if (DEBUGLEVEL>2) err_printf("first LLL: prec = %ld\n", prec); u = i? lllfp(a, 0.75, LLL_GRAM): ZM_lll(a, 0.75, LLL_GRAM); if (lg(u) != lg(a)) return NULL; r = qf_apply_ZM(a,u); if (!i) { prec = DEFAULTPREC + nbits2nlong(gexpo(r)); if (prec < PREC) prec = 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); r = Q_from_QR(r, gprecision(vnorm)); if (!r) pari_err(precer,"fincke_pohst"); res = smallvectors(r, bound, stockmax, CHECK); } ENDCATCH; if (CHECK) { if (CHECK->f_post) res = CHECK->f_post(CHECK, res, u); return res; } if (!res) pari_err(precer,"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.5.5/src/basemath/polarit1.c0000644000175000017500000020116512147140046015362 0ustar billbill/* $Id$ 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. */ /***********************************************************************/ /** **/ /** ARITHMETIC OPERATIONS ON POLYNOMIALS **/ /** (first part) **/ /** **/ /***********************************************************************/ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /* */ /* POLYNOMIAL EUCLIDEAN DIVISION */ /* */ /*******************************************************************/ GEN poldivrem(GEN x, GEN y, GEN *pr) { long ty = typ(y), tx, vx = gvar(x), vy = gvar(y); GEN p1; if (is_scalar_t(ty) || varncmp(vx, vy) < 0) { if (pr == ONLY_REM) { if (gequal0(y)) pari_err(gdiver); return gen_0; } if (pr && pr != ONLY_DIVIDES) *pr=gen_0; return gdiv(x,y); } if (ty != t_POL) pari_err(typeer,"euclidean division (poldivrem)"); tx = typ(x); if (is_scalar_t(tx) || varncmp(vx, vy) > 0) { if (!signe(y)) pari_err(gdiver); if (!degpol(y)) /* constant */ { if (pr == ONLY_REM) return pol_0(vy); p1 = gdiv(x, gel(y,2)); if (pr == ONLY_DIVIDES) return p1; if (pr) *pr = pol_0(vy); return p1; } if (pr == ONLY_REM) return gcopy(x); if (pr == ONLY_DIVIDES) return gequal0(x)? gen_0: NULL; if (pr) *pr = gcopy(x); return gen_0; } if (tx != t_POL) pari_err(typeer,"euclidean division (poldivrem)"); if (varncmp(vx, vy) < 0) { if (pr && pr != ONLY_DIVIDES) { p1 = pol_0(vx); if (pr == ONLY_REM) return p1; *pr = p1; } return gdiv(x,y); } return RgX_divrem(x, y, pr); } GEN gdeuc(GEN x, GEN y) { long ty = typ(y), tx, vx = gvar(x), vy = gvar(y); if (is_scalar_t(ty) || varncmp(vx, vy) < 0) return gdiv(x,y); if (ty != t_POL) pari_err(typeer,"euclidean division (poldivrem)"); tx = typ(x); if (is_scalar_t(tx) || varncmp(vx, vy) > 0) { if (!signe(y)) pari_err(gdiver); if (!degpol(y)) return gdiv(x, gel(y,2)); /* constant */ return gen_0; } if (tx != t_POL) pari_err(typeer,"euclidean division (poldivrem)"); if (varncmp(vx, vy) < 0) return gdiv(x,y); return RgX_div(x, y); } GEN grem(GEN x, GEN y) { long ty = typ(y), tx, vx = gvar(x), vy = gvar(y); if (is_scalar_t(ty) || varncmp(vx, vy) < 0) { if (gequal0(y)) pari_err(gdiver); return gen_0; } if (ty != t_POL) pari_err(typeer,"euclidean division (poldivrem)"); tx = typ(x); if (is_scalar_t(tx) || varncmp(vx, vy) > 0) { if (!signe(y)) pari_err(gdiver); if (!degpol(y)) return pol_0(vy); /* constant */ return gcopy(x); } if (tx != t_POL) pari_err(typeer,"euclidean division (poldivrem)"); if (varncmp(vx, vy) < 0) return pol_0(vx); return RgX_rem(x, y); } /*******************************************************************/ /* */ /* ROOTS MODULO a prime p (no multiplicities) */ /* */ /*******************************************************************/ static ulong init_p(GEN pp) { ulong p; if ((ulong)expi(pp) > BITS_IN_LONG - 3) p = 0; else { p = itou(pp); if (p < 2 || signe(pp) < 0) pari_err(talker,"not a prime in factmod"); } return p; } static long factmod_init(GEN *F, GEN p) { long d; if (typ(*F)!=t_POL || typ(p)!=t_INT) pari_err(typeer,"factmod"); *F = FpX_normalize(RgX_to_FpX(*F, p), p); d = degpol(*F); if (d < 0) pari_err(zeropoler,"factmod"); return d; } static GEN root_mod_2(GEN f) { int z1, z0 = !signe(constant_term(f)); long i,n; GEN y; for (i=2, n=1; i < lg(f); i++) if (signe(f[i])) n++; z1 = n & 1; y = cgetg(z0+z1+1, t_COL); i = 1; if (z0) gel(y,i++) = gen_0; if (z1) gel(y,i) = gen_1; return y; } #define i_mod4(x) (signe(x)? mod4((GEN)(x)): 0) static GEN root_mod_4(GEN f) { long i, no, ne; GEN y, t; int z0, z1, z2, z3; t = constant_term(f); z0 = !signe(t); z2 = ((i_mod4(t) + 2*i_mod4(f[3])) & 3) == 0; for (ne=0,i=2; i 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; } GEN rootmod2(GEN f, GEN pp) { pari_sp av = avma; ulong p; GEN y; if (!factmod_init(&f, pp)) { avma = av; return cgetg(1,t_COL); } p = init_p(pp); if (!p) pari_err(talker,"prime too big in rootmod2"); if (p & 1) y = Flc_to_ZC(Flx_roots_naive(ZX_to_Flx(f,p), p)); else y = root_mod_even(f,p); return gerepileupto(av, FpC_to_mod(y, pp)); } /* assume x reduced mod p, monic. */ static int FpX_quad_factortype(GEN x, GEN p) { GEN b = gel(x,3), c = gel(x,2); GEN D; if (equaliu(p, 2)) { if (!signe(b)) return 0; return signe(c)? -1: 1; } 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; } /* by splitting, assume p > 2 prime, deg(f) > 0, and f monic */ static GEN FpX_roots_i(GEN f, GEN p) { long n, j, da, db; GEN y, pol, pol0, a, b, q = shifti(p,-1); n = ZX_valrem(f, &f)? 1: 0; y = cgetg(lg(f), t_COL); j = 1; if (n) { gel(y, j++) = gen_0; if (lg(f) <= 3) { setlg(y, 2); return y; } n = 1; } da = degpol(f); if (da == 1) { gel(y,j++) = subii(p, gel(f,2)); setlg(y,j); return y; } if (da == 2) { GEN s, r = FpX_quad_root(f, p, 1); if (r) { gel(y, j++) = r; s = FpX_otherroot(f,r, p); if (!equalii(r, s)) gel(y, j++) = s; } setlg(y, j); return sort(y); } /* take gcd(x^(p-1) - 1, f) by splitting (x^q-1) * (x^q+1) */ b = FpXQ_pow(pol_x(varn(f)),q, f,p); if (lg(b) < 3) pari_err(talker,"not a prime in rootmod"); b = ZX_Z_add(b, gen_m1); /* b = x^((p-1)/2) - 1 mod f */ a = FpX_gcd(f,b, p); b = ZX_Z_add(b, gen_2); /* b = x^((p-1)/2) + 1 mod f */ b = FpX_gcd(f,b, p); da = degpol(a); db = degpol(b); n += da + db; setlg(y, n+1); if (db) gel(y,j) = FpX_normalize(b,p); if (da) gel(y,j+db) = FpX_normalize(a,p); pol0 = icopy(gen_1); /* constant term, will vary in place */ pol = deg1pol_shallow(gen_1, pol0, varn(f)); while (j <= n) { /* cf FpX_split_Berlekamp */ a = gel(y,j); da = degpol(a); if (da==1) gel(y,j++) = subii(p, gel(a,2)); else if (da==2) { GEN r = FpX_quad_root(a, p, 0); gel(y, j++) = r; gel(y, j++) = FpX_otherroot(a,r, p); } else for (pol0[2]=1; ; pol0[2]++) { b = ZX_Z_add(FpXQ_pow(pol,q, a,p), gen_m1); /* pol^(p-1)/2 - 1 */ b = FpX_gcd(a,b, p); db = degpol(b); if (db && db < da) { b = FpX_normalize(b, p); gel(y,j+db) = FpX_div(a,b, p); gel(y,j) = b; break; } if (pol0[2] == 100 && !BPSW_psp(p)) pari_err(talker, "not a prime in polrootsmod"); } } return sort(y); } static GEN FpX_oneroot_i(GEN f, GEN p) { long da, db; GEN pol, pol0, a, b, q = shifti(p,-1); if (ZX_val(f)) return gen_0; da = degpol(f); if (da == 1) return subii(p, gel(f,2)); if (da == 2) return FpX_quad_root(f, p, 1); /* take gcd(x^(p-1) - 1, f) by splitting (x^q-1) * (x^q+1) */ b = FpXQ_pow(pol_x(varn(f)),q, f,p); if (lg(b) < 3) pari_err(talker,"not a prime in rootmod"); b = ZX_Z_add(b, gen_m1); /* b = x^((p-1)/2) - 1 mod f */ a = FpX_gcd(f,b, p); b = ZX_Z_add(b, gen_2); /* b = x^((p-1)/2) + 1 mod f */ b = FpX_gcd(f,b, p); da = degpol(a); db = degpol(b); if (!da) { if (!db) return NULL; a = b; } else if (db && db < da) a = b; a = FpX_normalize(a,p); pol0 = icopy(gen_1); /* constant term, will vary in place */ pol = deg1pol_shallow(gen_1, pol0, varn(f)); for(;;) { /* cf FpX_split_Berlekamp */ da = degpol(a); if (da==1) return subii(p, gel(a,2)); if (da==2) return FpX_quad_root(a, p, 0); for (pol0[2]=1; ; pol0[2]++) { b = ZX_Z_add(FpXQ_pow(pol,q, a,p), gen_m1); /* pol^(p-1)/2 - 1 */ b = FpX_gcd(a,b, p); db = degpol(b); if (db && db < da) { b = FpX_normalize(b, p); a = (db <= (da >> 1))? b: FpX_div(a,b, p); break; } if (pol0[2] == 100 && !BPSW_psp(p)) pari_err(talker, "not a prime in polrootsmod"); } } } static GEN FpX_factmod_init(GEN f, GEN p) { return FpX_normalize(FpX_red(f,p), p); } GEN FpX_roots(GEN f, GEN p) { pari_sp av = avma; long q = mod2BIL(p); GEN F = FpX_factmod_init(f,p); switch(degpol(F)) { case -1: pari_err(zeropoler,"factmod"); case 0: avma = av; return cgetg(1, t_COL); } return gerepileupto(av, odd(q)? FpX_roots_i(F, p): root_mod_even(F,q)); } GEN FpX_oneroot(GEN f, GEN p) { pari_sp av = avma; long q = mod2BIL(p); GEN F = FpX_factmod_init(f,p); switch(degpol(F)) { case -1: pari_err(zeropoler,"factmod"); case 0: avma = av; return NULL; } if (!odd(q)) { F = root_mod_even(F,q); avma = av; return (lg(F) == 1)? NULL: gel(F,1); } F = FpX_oneroot_i(F, p); if (!F) { avma = av; return NULL; } return gerepileuptoint(av, F); } GEN rootmod(GEN f, GEN p) { ulong q; pari_sp av = avma; GEN y; if (!factmod_init(&f, p)) { avma=av; return cgetg(1,t_COL); } q = init_p(p); if (!q) q = mod2BIL(p); if (q & 1) y = FpX_roots_i(f, p); else y = root_mod_even(f,q); return gerepileupto(av, FpC_to_mod(y, p)); } 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(flagerr,"polrootsmod"); } return NULL; /* not reached */ } /*******************************************************************/ /* */ /* FACTORISATION MODULO p */ /* */ /*******************************************************************/ static GEN spec_FpXQ_pow(GEN x, GEN p, GEN S); /* 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_pow(polx_Flx(u[1]),utoipos(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); } GEN FqX_Berlekamp_ker(GEN u, GEN T, GEN q, GEN p) { pari_sp ltop=avma; long j,N = degpol(u); GEN v,w,Q,p1; pari_timer Ti; if (DEBUGLEVEL>=4) timer_start(&Ti); Q = cgetg(N+1,t_MAT); gel(Q,1) = zerocol(N); w = v = FpXQXQ_pow(pol_x(varn(u)), q, u, T, p); if (DEBUGLEVEL>=4) timer_printf(&Ti, "FpXQXQ_pow"); for (j=2; j<=N; j++) { p1 = RgX_to_RgV(w, N); gel(p1,j) = gaddgs(gel(p1,j), -1); gel(Q,j) = p1; if (j < N) { pari_sp av = avma; w = gerepileupto(av, FpXQX_divrem(FpXQX_mul(w,v, T,p), u,T,p,ONLY_REM)); } } if (DEBUGLEVEL>=4) timer_printf(&Ti, "Berlekamp_matrix"); p1 = FqM_ker(Q,T,p); if (DEBUGLEVEL>=4) timer_printf(&Ti, "Berlekamp_ker"); return gerepileupto(ltop,p1); } GEN FqX_deriv(GEN f, /*unused*/GEN T, GEN p) { (void)T; return FpXX_red(RgX_deriv(f), p); } /* 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); } static GEN FqX_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 = FpXQXQ_pow(X, powiu(p, degpol(T)), f, T, p); z = FpXX_sub(z, X , p); return FqX_gcd(z, f, T, p); } /* Compute the number of roots in Fq 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); } long FqX_nbroots(GEN f, GEN T, GEN p) { pari_sp av = avma; GEN z = FqX_split_part(f, T, 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(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 = lg(x[1]); y++; z = const_vecsmall(l,0) + 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_pow(X, utoipos(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; } long FqX_nbfact(GEN u, GEN T, GEN p) { pari_sp av = avma; GEN vker; if (!T) return FpX_nbfact(u, p); vker = FqX_Berlekamp_ker(u, T, powiu(p, degpol(T)), p); avma = av; return lg(vker)-1; } /************************************************************/ GEN trivfact(void) { GEN y = cgetg(3,t_MAT); gel(y,1) = gel(y,2) = cgetg(1,t_COL); return y; } /* polynomial in variable v, whose coeffs are the digits of m in base p */ static GEN stoFpX(ulong m, ulong p, long v) { GEN y = new_chunk(BITS_IN_LONG + 2); long l = 2; do { ulong q = m/p; gel(y,l++) = utoi(m - q*p); m=q; } while (m); y[1] = evalsigne(1) | evalvarn(v); y[0] = evaltyp(t_POL) | evallg(l); return y; } static GEN itoFpX(GEN m, GEN p, long v) { GEN y = new_chunk(bit_accuracy(lgefint(m))+2); long l = 2; do { m = dvmdii(m, p, &gel(y,l)); l++; } while (signe(m)); y[1] = evalsigne(1) | evalvarn(v); y[0] = evaltyp(t_POL) | evallg(l); return y; } 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 0 */ static GEN init_spec_FpXQ_pow(GEN p, GEN T) { long i, n = degpol(T), v = varn(T); GEN S = cgetg(n, t_VEC), x; if (n == 1) return S; x = FpXQ_pow(pol_x(v), p, T, p); gel(S,1) = x; if ((degpol(x)<<1) < degpol(T)) { for (i=2; i < n; i++) gel(S,i) = FpXQ_mul(gel(S,i-1), x, T,p); } else { for (i=2; i < n; i++) gel(S,i) = (i&1)? FpXQ_mul(gel(S,i-1), x, T,p) : FpXQ_sqr(gel(S,i>>1), T, p); } return S; } /* compute x^p, S is as above */ static GEN spec_FpXQ_pow(GEN x, GEN p, GEN S) { long i, dx = degpol(x); pari_sp av = avma, lim = stack_lim(av, 1); GEN x0 = x+2, z = gel(x0,0); if (dx < 0) pari_err(talker, "zero polynomial in FpXQ_pow. %Ps not prime", p); for (i = 1; i <= dx; i++) { GEN d, c = gel(x0,i); /* assume coeffs in [0, p-1] */ if (!signe(c)) continue; d = gel(S,i); if (!gequal1(c)) d = ZX_Z_mul(d, c); z = typ(z) == t_INT? ZX_Z_add(d,z): ZX_add(d,z); if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"spec_FpXQ_pow"); z = gerepileupto(av, z); } } return gerepileupto(av, FpX_red(z, p)); } static int cmpGsGs(GEN a, GEN b) { return (long)a - (long)b; } static GEN FpX_is_irred_2(GEN f, GEN p, long d) { if (!d) return NULL; if (d == 1) return gen_1; return FpX_quad_factortype(f, p) == -1? gen_1: NULL; } static GEN FpX_degfact_2(GEN f, GEN p, long d) { if (!d) return trivfact(); if (d == 1) return mkvec2(mkvecsmall(1), mkvecsmall(1)); switch(FpX_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)); } } static GEN FpX_factor_2(GEN f, GEN p, long d) { GEN r, s, R, S; long v; int sgn; if (d < 0) pari_err(zeropoler,"FpX_factor_2"); if (!d) return mkvec2(cgetg(1,t_COL), cgetg(1,t_VECSMALL)); if (d == 1) return mkvec2(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)); } /* factor f mod pp. * flag = 1: return the degrees, not the factors * flag = 2: return NULL if f is not irreducible */ static GEN FpX_factcantor_i(GEN f, GEN pp, long flag) { long j, e, vf, nbfact, d = degpol(f); ulong p, k; GEN E,y,f2,g,g1,u,v,pd,q; GEN *t; if (d <= 2) switch(flag) { case 2: return FpX_is_irred_2(f, pp, d); case 1: return FpX_degfact_2(f, pp, d); default: return FpX_factor_2(f, pp, d); } p = init_p(pp); /* to hold factors and exponents */ t = (GEN*)cgetg(d+1,t_VEC); E = cgetg(d+1, t_VECSMALL); vf=varn(f); e = nbfact = 1; for(;;) { f2 = FpX_gcd(f,ZX_deriv(f), pp); if (flag > 1 && lg(f2) > 3) return NULL; g1 = FpX_div(f,f2,pp); k = 0; while (lg(g1)>3) { long du,dg; GEN S; k++; if (p && !(k%p)) { k++; f2 = FpX_div(f2,g1,pp); } u = g1; g1 = FpX_gcd(f2,g1, pp); if (lg(g1)>3) { 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) */ S = init_spec_FpXQ_pow(pp, u); pd=gen_1; v=pol_x(vf); for (d=1; d <= du>>1; d++) { if (!flag) pd = mulii(pd,pp); v = spec_FpXQ_pow(v, pp, S); g = FpX_gcd(ZX_sub(v, pol_x(vf)), 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 > 1) return NULL; for ( ; nbfact w_m = X). Take * gcd(g, w_m^(p^d-1)/2), m++, until a factor is found. p = 2 is * treated separately */ if (p) split(p,t+nbfact,d,pp,q,r,S); else splitgen(pp,t+nbfact,d,pp,q,r); for (; nbfact 1) return gen_1; /* irreducible */ setlg(t, nbfact); setlg(E, nbfact); y = mkvec2((GEN)t, E); return flag ? sort_factor(y, (void*)&cmpGsGs, cmp_nodata) : sort_factor_pol(y, cmpii); } GEN FpX_factcantor(GEN f, GEN pp, long flag) { pari_sp av = avma; GEN z = FpX_factcantor_i(FpX_factmod_init(f,pp),pp,flag); if (flag == 2) { avma = av; return z; } return gerepilecopy(av, z); } GEN factcantor0(GEN f, GEN pp, long flag) { pari_sp av = avma; long j, nbfact; GEN z, y, t, E, u, v; if (! factmod_init(&f, pp)) { avma=av; return trivfact(); } z = FpX_factcantor_i(f,pp,flag); t = gel(z,1); E = gel(z,2); y = cgetg(3, t_MAT); nbfact = lg(t); u = cgetg(nbfact,t_COL); gel(y,1) = u; v = cgetg(nbfact,t_COL); gel(y,2) = v; if (flag) for (j=1; jir) swap(t[i],t[ir]); ir++;} long FpX_split_Berlekamp(GEN *t, GEN p) { GEN u = *t, a,b,po2,vker; long d, i, ir, L, la, lb, vu = varn(u), sv = evalvarn(vu); long l = lg(u); ulong ps = itou_or_0(p); if (ps==2) vker = F2x_Berlekamp_ker(ZX_to_F2x(u)); else if (ps) { vker = Flx_Berlekamp_ker(ZX_to_Flx(u,ps),ps); vker = Flm_to_FlxV(vker, sv); } else { vker = FpX_Berlekamp_ker(u,p); vker = RgM_to_RgXV(vker,vu); } d = lg(vker)-1; po2 = shifti(p, -1); /* (p-1) / 2 */ ir = 0; /* t[i] irreducible for i <= ir, still to be treated for i < L */ for (L=1; L3) { k++; if (p && !(k%p)) { k++; f2 = FpX_div(f2,g1,pp); } u = g1; if (!degpol(f2)) g1 = pol_1(0); /* only its degree (= 0) matters */ else { g1 = FpX_gcd(f2,g1, pp); if (degpol(g1)) { u = FpX_div( u,g1,pp); f2= FpX_div(f2,g1,pp); } } /* u is square-free (product of irred. of multiplicity e * k) */ N = degpol(u); if (N > 0) { t[nbfact] = FpX_normalize(u,pp); d = (N==1)? 1: FpX_split_Berlekamp(t+nbfact, pp); 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(talker, "factmod: %lu is not prime", p); e *= p; f = RgX_deflate(f2, p); } setlg(t, nbfact); setlg(E, nbfact); return sort_factor_pol(mkvec2((GEN)t,E), cmpii); } GEN FpX_factor(GEN f, GEN p) { pari_sp av = avma; return gerepilecopy(av, FpX_factor_i(FpX_factmod_init(f, p), p)); } GEN factmod(GEN f, GEN p) { pari_sp av = avma; long nbfact; long j; GEN y, u, v, z, t, E; if (!factmod_init(&f, p)) { avma = av; return trivfact(); } z = FpX_factor_i(f, p); t = gel(z,1); E = gel(z,2); y = cgetg(3,t_MAT); nbfact = lg(t); u = cgetg(nbfact,t_COL); gel(y,1) = u; v = cgetg(nbfact,t_COL); gel(y,2) = v; for (j=1; j= prec */ static GEN ZX_Zp_root(GEN f, GEN a, GEN p, long prec) { GEN z, R, a0 = modii(a, p); long i, j, k; if (signe(FpX_eval(FpX_deriv(f, p), a0, p))) { /* simple zero mod p, go all the way to p^prec */ if (prec > 1) a0 = ZpX_liftroot(f, a0, p, prec); return mkcol(a0); } f = poleval(f, deg1pol_shallow(p, a, varn(f))); f = ZX_Z_divexact(f, powiu(p,ggval(f, p))); z = cgetg(degpol(f)+1,t_COL); R = FpX_roots(f, p); for (j=i=1; i1; i--) scalar_getprec(gel(x,i), pprec, pp); } static GEN FqX_roots_i(GEN f, GEN T, GEN p); static GEN ZXY_ZpQ_root(GEN f, GEN a, GEN T, GEN p, long prec) { GEN z, R; long i, j, k, lR; if (signe(FqX_eval(FqX_deriv(f,T,p), a, T,p))) { /* simple zero mod (T,p), go all the way to p^prec */ if (prec > 1) a = ZpXQX_liftroot(f, a, T, p, prec); return mkcol(a); } /* TODO: need RgX_RgYQX_compo ? */ f = lift_intern(poleval(f, deg1pol_shallow(p, mkpolmod(a,T), varn(f)))); f = gdiv(f, powiu(p, ggval(f,p))); z = cgetg(degpol(f)+1,t_COL); R = FqX_roots_i(FqX_red(f,T,p), T, p); lR = lg(R); 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(typeer,"padicappr"); f = QpXQ_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] */ /* */ /*******************************************************************/ 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)); } /*******************************/ /* Using Buchmann--Lenstra */ /*******************************/ /* factor T = nf_get_pol(nf) in Zp to precision k */ static GEN padicff2(GEN nf,GEN p,long k) { GEN z, mat, D, U, fa, pk, dec_p, Ui, mulx; long i, l; mulx = zk_scalar_or_multable(nf, gmael(nf,8,2)); /* mul by (x mod T) */ dec_p = idealprimedec(nf,p); fa = cgetg_copy(dec_p, &l); D = NULL; /* -Wall */ 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 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 x0, P, u, fa, n; long lx, i, k; u = A; n = NULL; for (k = 0; cmpui(k, p) < 0; k++) { GEN U = poleval(u, deg1pol_shallow(gen_1, gmulsg(k, pol_x(varn(T))), varn(A))); 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); x0 = gadd(pol_x(varn(A)), gmulsg(-k, mkpolmod(pol_x(varn(T)), T))); for (i=lx-1; i>1; i--) { GEN f = gel(fa,i), F = lift_intern(poleval(f, x0)); F = FqX_normalize(FqX_gcd(u, F, T, p), T, p); if (typ(F) != t_POL || degpol(F) == 0) pari_err(talker,"reducible modulus in FqX_split_Trager"); u = FqX_div(u, F, T, p); gel(P,i) = F; } gel(P,1) = u; return P; } /* assume n = deg(u) > 1, X over FqX */ /* return S = [ X^q, X^2q, ... X^(n-1)q ] mod u (in Fq[X]) in Kronecker form */ static GEN init_spec_FqXQ_pow(GEN X, GEN q, GEN u, GEN T, GEN p) { long i, n = degpol(u); GEN x, S = cgetg(n, t_VEC); if (n == 1) return S; x = FpXQXQ_pow(X, q, u, T, p); gel(S,1) = x; if ((degpol(x)<<1) < degpol(T)) { for (i=2; i < n; i++) gel(S,i) = FqX_rem(FqX_mul(gel(S,i-1), x, T,p), u, T,p); } else { for (i=2; i < n; i++) gel(S,i) = (i&1)? FqX_rem(FqX_mul(gel(S,i-1), x, T,p), u, T,p) : FqX_rem(FqX_sqr(gel(S,i>>1), T,p), u, T,p); } for (i=1; i < n; i++) gel(S,i) = mod_to_Kronecker(gel(S,i), T); return S; } /* compute x^q, x an FqX. S is as above (vector of FpX, Kronecker forms) */ static GEN spec_FqXQ_pow(GEN x, GEN S, GEN T, GEN p) { pari_sp av = avma, lim = stack_lim(av, 1); GEN x0 = x+2, z = gel(x0,0); long i, dx = degpol(x); for (i = 1; i <= dx; i++) { /* NB: variables are inconsistant in there. Coefficients of x must be * treated as if they had the same variable as S */ GEN d = gel(S,i), c = gel(x0,i); if (!signe(c)) continue; if (typ(c) == t_INT) { if (is_pm1(c)) { if (signe(c) < 0) d = FpX_neg(d,p); } else d = FpX_Fp_mul(d, c, p); } else /* FpX */ { if (!degpol(c)) d = FpX_Fp_mul(d, gel(c,2), p); else d = FpX_mul(d, c, p); } z = typ(z)==t_INT? FpX_Fp_add(d, z, p) : FpX_add(d, z, p); if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"spec_FqXQ_pow"); z = gerepileupto(av, z); } } z[1] = x[1]; /* make sure variable number is sane */ z = Kronecker_to_FpXQX(z, T, p); return gerepileupto(av, z); } 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 q, 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 = init_spec_FqXQ_pow(X, q, u, T, p); vectrunc_append(z, S); v = spec_FqXQ_pow(v, S, 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 q, 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 = init_spec_FqXQ_pow(X, q, u, T, p); vectrunc_append(z, S); for (d=1; d <= N>>1; d++) { v = spec_FqXQ_pow(v, S, 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=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); } static GEN F2xqX_quad_roots(GEN P, GEN T) { GEN b= gel(P,3), c = gel(P,2); if (degpol(b)>=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,T[1]); s = F2xqX_quad_roots(f2, ZX_to_F2x(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(zeropoler,"FqX_roots"); if (isabsolutepol(f)) { f = simplify_shallow(f); if (typ(f) == t_INT) return cgetg(1, t_COL); return FpX_rootsff_i(f, p, T); } if (degpol(f)==2) return gen_sort(FqX_quad_roots(f,T,p), (void*) &cmp_RgX, &cmp_nodata); switch( FqX_split_deg1(&R, f, powiu(p, degpol(T)), 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 = init_spec_FqXQ_pow(X, q, u, T, p); for (d=1; d <= N>>1; d++) { v = spec_FqXQ_pow(v, S, 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 p, GEN T) { GEN V, E, F = FpX_factor(P,p); long i, lfact = 1, nmax = lgpol(P), n = lg(gel(F,1)); 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, d, e, N, lfact, pk; GEN E, f2, f3, df1, df2, g1, u, q, *t; if (!signe(f)) pari_err(zeropoler,"FqX_factor"); d = degpol(f); if (!d) return trivfact(); T = FpX_normalize(T, p); f = FqX_normalize(f, T, p); if (isabsolutepol(f)) return FpX_factorff_i(simplify_shallow(f), p, T); pg = itos_or_0(p); df2 = NULL; /* gcc -Wall */ t = (GEN*)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; t[lfact] = FqX_normalize(u, T,p); if (N == 1) lfact++; else { #if 0 lfact += FqX_split_Berlekamp(t+lfact, q, T, p); #else GEN P = FqX_split_Trager(t[lfact], T, p); if (P) { for (j = 1; j < lg(P); j++) t[lfact++] = gel(P,j); } else { if (DEBUGLEVEL) pari_warn(warner, "FqX_split_Trager failed!"); lfact += FqX_sqf_split(t+lfact, q, T, p); } #endif } 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 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++) t[i] = 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++) t[i] = 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++) t[i] = 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++) t[i] = 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; p0 = new_chunk(n0); for (i=0; i 10) return maxdd(x,y); return x + 0.5*log2(1 + exp2(2*(y-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*)stackmalloc((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(z[1])) setexpo(z[1], expo(z[1])+e); if (signe(z[2])) setexpo(z[2], expo(z[2])+e); } else if (signe(z)) setexpo(z,expo(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(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 */ 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); setexpo(r, expo(r) - M); avma = ltop; return -rtodbl(r) * LOG2; /* -log(2) sum e_i 2^-i */ } GEN logmax_modulus_bound(GEN P) { return 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 || !is_vec_t(typ(x)) || typ(Omega) != t_VEC) pari_err(typeer,"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(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 = dblogr(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 = dblogr(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++) pc[i]= q[i]; for ( ; i0 && i1) pari_warn(warnmem,"parameters"); gerepileall(av2,2, &g,&RU); } } *gamma = dblogr(divru(g,NN)) / LOG2; *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 = gmul(mygprec(H,bit1), mygprec(D,bit1)); aux = grem(mygprec(aux,bit1), mygprec(F,bit1)); bit1 = -error*2 + Sbit; if (bit1 > bit2) bit1 = bit2; H = gadd(mygprec(H,bit1), aux); D = gsub(gen_1, grem(gmul(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 = poldivrem(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 = gmul(mygprec(HH,bit1), mygprec(r,bit1)); f0 = grem(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 = poldivrem(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] = dblogr(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*) stackmalloc((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 pari_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), pari_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 pari_err) { long i, e, n = degpol(p), e_max = -(long)EXPOBITS; GEN sigma, shatzle, x; pari_err += (long)log2((double)n) + 1; if (pari_err > -2) return 0; sigma = real2n(-pari_err, 3); /* 2 / ((s - 1)^(1/n) - 1) */ shatzle = divur(2, subrs(sqrtnr(subrs(sigma,1),n), 1)); for (i=1; i<=n; i++) { x = root_error(n,i,roots_pol,pari_err,shatzle); e = gexpo(x); 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(typeer,"quickabs"); 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(constpoler,"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 = dblogr(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 > lg(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) 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 long isvalidpol(GEN p) { long i,n = lg(p); for (i=2; i 0) real = 0; break; default: real = 0; } } av1 = avma; k = RgX_valrem_inexact(x, &pax); for (i = 1; i <= k; i++) gaffsg(0,gel(y,i)); if (k == deg0) return y; mask0 = quadratic_prec_mask(prec-2); pi = mppi(DEFAULTPREC); p2 = mkcomplex(pi, divru(pi,10)); /* Pi * (1+I/10) */ p11 = cgetg(4,t_POL); p11[1] = x[1]; gel(p11,3) = gen_1; p12 = cgetg(5,t_POL); p12[1] = x[1]; gel(p12,4) = gen_1; xd0 = RgX_deriv(pax); pa = pax; pq = NULL; /* for lint */ if (exact) { pp = RgX_gcd(pax,xd0); h = degpol(pp); if (h) pq = RgX_div(pax,pp); } else { pp = gen_1; h = 0; } m = 0; while (k != deg0) { m++; if (h) { pa = pp; pb = pq; pp = RgX_gcd(pa,RgX_deriv(pa)); h = degpol(pp); pq = h? RgX_div(pa,pp): pa; ps = RgX_div(pb,pq); } else ps = pa; deg = degpol(ps); if (!deg) continue; /* roots of exact order m */ e = gexpo(ps) - gexpo(leading_term(ps)); if (e < 0) e = 0; if (ps != pax) xd0 = RgX_deriv(ps); xdabs = cgetg(deg+2,t_POL); xdabs[1] = xd0[1]; for (i=2; i 10) { if (DEBUGLEVEL) pari_warn(warner,"too many iterations in rootsold(): using roots2()"); avma = av; return roots2(x,prec); } } z = gel(y,k+m*i); setlg(gel(z,1), 3); setlg(gel(z,2), 3); gaffect(p3, z); avma = av2; ln = 1; mask = mask0; while (mask > 1) { GEN p6; ln <<= 1; if (mask & 1) ln--; mask >>= 1; setlg(gel(z,1), ln+2); setlg(gel(z,2), ln+2); p6 = signe(gel(z,2))? z: gel(z,1); p6 = gsub(z, gdiv(poleval(xc,p6), poleval(xd,p6))); gaffect(p6, z); avma = av2; } } p7 = gtofp(z, prec+1); for (j=1; j<=5; j++) { if (typ(p7) == t_COMPLEX && !signe(gel(p7,2))) p7 = gel(p7,1); p7 = gsub(p7, gdiv(poleval(ps,p7), poleval(xd0,p7))); } gaffect(p7, z); if (gexpo(poleval(ps,p7)) - gexpo(poleval(xdabs,gabs(p7,prec))) >= expmin) { if (DEBUGLEVEL) pari_warn(warner,"error in rootsold(): using roots2()"); avma = av; return roots2(x,prec); } avma = av2; if (expo(z[2]) < expmin && real) { affsr(0, gel(z,2)); for (j=1; j=1; k--) { GEN t = gel(y,k); f = !gequal0(gel(t,2)); if (!f && fr) break; if (f == fr && gcmp(gel(t,1),gel(z,1)) <= 0) break; y[k+1] = y[k]; } gel(y,k+1) = z; } return y; } static GEN roots2(GEN T, long PREC) { pari_sp av = avma; long N,flagexactpol,flagrealpol,flagrealrac,ti,i,j; long nbpol, k, multiqol, deg, nbroot, fr, f, EPS; pari_sp av1; GEN p1,p2,rr,qol,qolbis,x,b,c,ad,v, ex, factors, pol = T; if (typ(pol)!=t_POL) pari_err(typeer,"roots2"); if (!signe(pol)) pari_err(zeropoler,"roots2"); N=degpol(pol); if (!N) return cgetg(1,t_COL); if (N==1) { p2 = gneg_i(gdiv(gel(pol,2), gtofp(gel(pol,3), PREC))); return gerepilecopy(av,p2); } EPS = 12 - bit_accuracy(PREC); /* 2^EPS is "zero" */ flagrealpol = flagexactpol = 1; for (i=2; i<=N+2; i++) { c = gel(pol,i); switch (typ(c)) { case t_INT: case t_FRAC: break; case t_REAL: flagexactpol = 0; break; case t_COMPLEX: flagexactpol = flagrealpol = 0; break; case t_QUAD: flagexactpol = 0; if (gsigne(gmael(c,1,2)) > 0) flagrealpol = 0; break; default: pari_err(typeer, "roots2"); } } rr=cgetg(N+1,t_COL); for (i=1; i<=N; i++) { p1 = cgetc(PREC); gel(rr,i) = p1; for (j=3; j=1; j--) { x = gen_0; flagrealrac = 0; if (j==1) x = gneg_i(gdiv(gel(qolbis,2),gel(qolbis,3))); else { x = laguer(qolbis,j,x,EPS,PREC); if (x == NULL) goto RLAB; } if (flagexactpol) { x = gprec_w(x, PREC+2); x = laguer(qol,deg,x, EPS-BITS_IN_LONG, PREC+1); } else x = laguer(qol,deg,x,EPS,PREC); if (x == NULL) goto RLAB; if (typ(x)==t_COMPLEX && gexpo(imag_i(x)) <= gexpo(real_i(x)) + EPS+1) { gel(x,2) = gen_0; flagrealrac = 1; } else if (j==1 && flagrealpol) { gel(x,2) = gen_0; flagrealrac = 1; } else if (typ(x)!=t_COMPLEX) flagrealrac = 1; for (i=1; i<=multiqol; i++) gaffect(x, gel(rr,nbroot+i)); nbroot += multiqol; if (!flagrealpol || flagrealrac) { ad = new_chunk(j+1); for (i=0; i<=j; i++) ad[i] = qolbis[i+2]; b = gel(ad,j); for (i=j-1; i>=0; i--) { c = gel(ad,i); gel(ad,i) = b; b = gadd(gmul(gel(rr,nbroot),b),c); } v = cgetg(j+1,t_VEC); for (i=1; i<=j; i++) v[i] = ad[j-i]; qolbis = gtopoly(v,varn(qolbis)); if (flagrealpol) for (i=2; i<=j+1; i++) if (typ(qolbis[i])==t_COMPLEX) gmael(qolbis,i,2)= gen_0; } else { ad = new_chunk(j-1); ad[j-2] = qolbis[j+2]; p1 = gmulsg(2,real_i(gel(rr,nbroot))); p2 = gnorm(gel(rr,nbroot)); gel(ad,j-3) = gadd(gel(qolbis,j+1), gmul(p1,gel(ad,j-2))); for (i=j-2; i>=2; i--) gel(ad,i-2) = gadd(gel(qolbis,i+2), gsub(gmul(p1,gel(ad,i-1)), gmul(p2,gel(ad,i)))); v = cgetg(j,t_VEC); for (i=1; i<=j-1; i++) v[i] = ad[j-1-i]; qolbis = gtopoly(v,varn(qolbis)); for (i=2; i<=j; i++) if (typ(qolbis[i])==t_COMPLEX) gmael(qolbis,i,2)= gen_0; for (i=1; i<=multiqol; i++) gaffect(gconj(gel(rr,nbroot)), gel(rr,nbroot+i)); nbroot+=multiqol; j--; } } avma=av1; } for (j=2; j<=N; j++) { x=gel(rr,j); if (gequal0(gel(x,2))) fr=0; else fr=1; for (i=j-1; i>=1; i--) { if (gequal0(gmael(rr,i,2))) f=0; else f=1; if (f=0; j--) { f = gadd(gmul(x,f), d); d = gadd(gmul(x,d), b); b = gadd(gmul(x,b), gel(pol,j+2)); erre = gadd(gnorml1_fake(b), gmul(abx,erre)); } erre = gmul2n(erre, EPS); if (gcmp(gnorml1_fake(b),erre)<=0) { gaffect(x,rac); avma = av1; return rac; } g = gdiv(d,b); g2 = gsqr(g); h = gsub(g2, gmul2n(gdiv(f,b),1)); sq = gsqrt(gmulsg(N-1,gsub(gmulsg(N,h),g2)),PREC); gp = gadd(g,sq); abp = gnorm(gp); gm = gsub(g,sq); abm = gnorm(gm); if (gcmp(abp,abm) < 0) gp = gm; if (gsigne(gmax(abp,abm)) > 0) dx = gdivsg(N,gp); else dx = gmul(gadd(gen_1,abx), gexp(gmulgs(I,iter),PREC)); x1 = gsub(x,dx); if (gexpo(gnorml1_fake(gsub(x,x1))) < EPS) { gaffect(x,rac); avma = av1; return rac; } if (iter%MT) x = gcopy(x1); else x = gsub(x, gmul(ffrac[iter/MT],dx)); } avma = av; return NULL; } /***********************************************************************/ /** **/ /** ROOTS of a polynomial with REAL coeffs **/ /** **/ /***********************************************************************/ /* x t_MAT in M_n(R) : compute a symmetric matrix with the same eigenvalues */ static GEN balanc(GEN x) { const long RADIX = 1; pari_sp av = avma; long i, j, sqrdx = (RADIX<<1), n = lg(x); GEN r, c, cof = dbltor(0.95), a = RgM_shallowcopy(x); for(;;) { int last = 1; for (i=1; i 0) {ex--; c=gmul2n(c,-sqrdx);} if (gcmp(gadd(c,r), gmul2n(s,ex)) < 0) { last = 0; for (j=1; j=0.0 ? fabs(a) : -fabs(a)) /* find the eigenvalues of the symmetric matrix mat */ static GEN hqr(GEN mat) { long n = lg(mat)-1, N, m, l, k, j, i, mmin, flj, flk; double **a, p, q, r, s, t, u, v, w, x, y, z, anorm, *wr, *wi; const double eps = 0.000001; GEN eig; init_dalloc(); a = (double**)stackmalloc(sizeof(double*)*(n+1)); for (i=1; i<=n; i++) a[i] = (double*)stackmalloc(sizeof(double)*(n+1)); for (j=1; j<=n; j++) for (i=1; i<=n; i++) a[i][j] = gtodouble(gcoeff(mat,i,j)); wr = (double*)stackmalloc(sizeof(double)*(n+1)); wi = (double*)stackmalloc(sizeof(double)*(n+1)); anorm = fabs(a[1][1]); for (i=2; i<=n; i++) for (j=(i-1); j<=n; j++) anorm += fabs(a[i][j]); N = n; t = 0.; p = q = r = 0.; /* -Wall */ if (DEBUGLEVEL>3) { err_printf("* Finding eigenvalues\n"); err_flush(); } while (N>=1) { long its = 0; for(;;) { for (l=N; l>=2; l--) { s = fabs(a[l-1][l-1])+fabs(a[l][l]); if (s==0.) s = anorm; if (fabs(a[l][l-1])+s == s) break; } x = a[N][N]; if (l == N){ wr[N] = x+t; wi[N] = 0.; N--; break; } /* OK */ y = a[N-1][N-1]; w = a[N][N-1]*a[N-1][N]; if (l == N-1) { p = 0.5*(y-x); q = p*p+w; z = sqrt(fabs(q)); x += t; if (q >= 0. || fabs(q) <= eps) { z = p + SIGN(z,p); wr[N-1] = wr[N] = x+z; if (fabs(z)>eps) wr[N] = x-w/z; wi[N-1] = wi[N] = 0.; } else { wr[N-1] = wr[N]= x+p; wi[N-1] = -z; wi[N] = z; } N -= 2; break; /* OK */ } if (its==30) pari_err(talker,"too many iterations in hqr"); if (its==10 || its==20) { t += x; for (i=1; i<=N; i++) a[i][i] -= x; s = fabs(a[N][N-1]) + fabs(a[N-1][N-2]); y = x = 0.75*s; w = -0.4375*s*s; } its++; for (m=N-2; m>=l; m--) { z = a[m][m]; r = x-z; s = y-z; p = (r*s-w)/a[m+1][m]+a[m][m+1]; q = a[m+1][m+1]-z-r-s; r = a[m+2][m+1]; s = fabs(p)+fabs(q)+fabs(r); p/=s; q/=s; r/=s; if (m==l) break; u = fabs(a[m][m-1])*(fabs(q)+fabs(r)); v = fabs(p) * (fabs(a[m-1][m-1])+fabs(z)+fabs(a[m+1][m+1])); if (u+v==v) break; } for (i=m+2; i<=N; i++){ a[i][i-2]=0.; if (i!=m+2) a[i][i-3]=0.; } for (k=m; k<=N-1; k++) { if (k!=m) { p = a[k][k-1]; q = a[k+1][k-1]; r = (k != N-1)? a[k+2][k-1]: 0.; x = fabs(p)+fabs(q)+fabs(r); if (x != 0.) { p/=x; q/=x; r/=x; } } s = SIGN(sqrt(p*p+q*q+r*r),p); if (s == 0.) continue; if (k==m) { if (l!=m) a[k][k-1] = -a[k][k-1]; } else a[k][k-1] = -s*x; p+=s; x=p/s; y=q/s; z=r/s; q/=p; r/=p; for (j=k; j<=N; j++) { p = a[k][j]+q*a[k+1][j]; if (k != N-1) { p+=r*a[k+2][j]; a[k+2][j]-=p*z; } a[k+1][j] -= p*y; a[k][j] -= p*x; } mmin = (N < k+3)? N: k+3; for (i=l; i<=mmin; i++) { p = x*a[i][k]+y*a[i][k+1]; if (k != N-1) { p+=z*a[i][k+2]; a[i][k+2]-=p*r; } a[i][k+1] -= p*q; a[i][k] -= p; } } } } for (j=2; j<=n; j++) /* ordering the roots */ { x = wr[j]; y = wi[j]; flj = (y != 0.); for (k=j-1; k>=1; k--) { flk = (wi[k] != 0.); if (!flk && flj) break; if (flk == flj && wr[k] <= x) break; wr[k+1] = wr[k]; wi[k+1] = wi[k]; } wr[k+1] = x; wi[k+1] = y; } if (DEBUGLEVEL>3) { err_printf("* Eigenvalues computed\n"); err_flush(); } eig = cgetg(n+1,t_COL); for (i=1; i<=n; i++) gel(eig,i) = (wi[i] == 0.)? dbltor(wr[i]) : mkcomplex(dbltor(wr[i]), dbltor(wi[i])); return eig; } /* a t_POL in R[X], squarefree: give the roots of the polynomial a (real roots * first) in increasing order of their real parts. */ static GEN zrhqr(GEN a, long prec) { pari_sp av = avma; long i, prec2, n = degpol(a), ex = -bit_accuracy(prec); GEN aa, b, rt, rr, x, dx, y, newval, oldval; rt = hqr(balanc(matcompanion(a))); prec2 = 2*prec; /* polishing the roots */ aa = gprec_w(a, prec2); b = RgX_deriv(aa); rr = cgetg(n+1,t_COL); for (i=1; i<=n; i++) { x = gprec_w(gel(rt,i), prec2); for (oldval=NULL;; oldval=newval, x=y) { /* Newton iteration */ dx = poleval(b,x); if (gexpo(dx) < ex) pari_err(talker,"polynomial has probably multiple roots in zrhqr"); y = gsub(x, gdiv(poleval(aa,x),dx)); newval = gabs(poleval(aa,y),prec2); if (gexpo(newval) < ex || (oldval && gcmp(newval,oldval) > 0)) break; } if (DEBUGLEVEL>3) err_printf("%ld ",i); gel(rr,i) = gtofp(y, prec); } if (DEBUGLEVEL>3) { err_printf("\npolished roots = %Ps",rr); err_flush(); } return gerepilecopy(av, rr); } pari-2.5.5/src/basemath/gen3.c0000644000175000017500000026723012212110474014463 0ustar billbill/* $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. */ /********************************************************************/ /** **/ /** GENERIC OPERATIONS **/ /** (third part) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" /********************************************************************/ /** **/ /** PRINCIPAL VARIABLE NUMBER **/ /** **/ /********************************************************************/ long gvar(GEN x) { long i, v, w; 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: v = NO_VARIABLE; for (i=1; i < lg(x); i++) { w=gvar(gel(x,i)); if (varncmp(w,v) < 0) v=w; } return v; case t_VECSMALL: case t_STR: case t_LIST: pari_err(typeer, "gvar"); } return NO_VARIABLE; } /* 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) ? lg(x): prec0(expo(x)); } /* t t_REAL, s an exact non-complex type. Return precision(|t| + |s|) */ static long precrealexact(GEN t, GEN s) { long l, e = gexpo(s); if (e == -(long)HIGHEXPOBIT) return precREAL(t); if (e < 0) e = 0; e -= expo(t); if (!signe(t)) return prec0(-e); l = lg(t); return (e > 0)? l + divsBIL(e): l; } 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 = lg(y); if (lz > ly) lz = ly; return lz; } if (!signe(y)) { if (e >= 0) return prec0(ey); lz = nbits2prec(-e); lx = lg(x); if (lz > lx) lz = lx; return lz; } if (e < 0) { swap(x, y); e = -e; } lx = lg(x); ly = lg(y); if (e) { long d = divsBIL(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 && l1; i--) { t = padicprec(gel(x,i),p); if (t0; i--) { t = padicprec(gel(x,i),p); if (t= 0, * wrt to main variable if v < 0. */ long poldegree(GEN x, long v) { 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 (v < w) 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(typeer,"degree"); 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(typeer,"pollead"); 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(typeer,"pollead"); 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(x[1])==t_REAL || typ(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(typeer,"isrealappr"); 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(typeer,"iscomplex"); 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; } static GEN _quotsg(long x, GEN y) { GEN q = gdivsg(x,y), f = gfloor(q); if (gsigne(y) < 0 && !gequal(f,q)) f = gaddgs(f, 1); return f; } static GEN _quotgs(GEN x, long y) { GEN q = gdivgs(x,y), f = gfloor(q); if (y < 0 && !gequal(f,q)) f = gaddgs(f, 1); return f; } static GEN quot(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, _quot(x, y)); } static GEN quotgs(GEN x, long y) { pari_sp av = avma; return gerepileupto(av, _quotgs(x, y)); } static GEN quotsg(long x, GEN y) { pari_sp av = avma; return gerepileupto(av, _quotsg(x, y)); } /* 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) > lg(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; } /* x t_POLMOD, y t_POL in the same variable as x[1], return x % y */ static GEN polmod_mod(GEN x, GEN y) { GEN z, T = gel(x,1); if (RgX_equal_var(T, y)) return gcopy(x); z = cgetg(3,t_POLMOD); T = RgX_gcd(T,y); gel(z,1) = T; gel(z,2) = grem(gel(x,2), T); return z; } GEN gmod(GEN x, GEN y) { pari_sp av, tetpil; long i,lx,ty, tx = typ(x); GEN z,p1; if (is_matvec_t(tx)) { z = cgetg_copy(x, &lx); for (i=1; i 0) return degpol(y)? gcopy(x): gen_0; if (varn(x[1])!=varn(y)) return gen_0; return polmod_mod(x, y); } switch(tx) { case t_POL: return grem(x,y); case t_RFRAC: av=avma; p1=gmul(gel(x,1),ginvmod(gel(x,2),y)); tetpil=avma; return gerepile(av,tetpil,grem(p1,y)); case t_SER: if (RgX_is_monomial(y) && varn(x) == varn(y)) { long d = degpol(y); if (lg(x)-2 + valp(x) < d) pari_err(operi,"%",x,y); av = avma; return gerepileupto(av, gmod(ser2rfrac_i(x), y)); } default: pari_err(operf,"%",x,y); } } pari_err(operf,"%",x,y); return NULL; /* not reached */ } /* divisibility: return 1 if y | x, 0 otherwise */ int gdvd(GEN x, GEN y) { pari_sp av = avma; x = gmod(x,y); avma = av; return gequal0(x); } GEN gmodgs(GEN x, long y) { ulong u; long i, lx, tx = typ(x); GEN z; if (is_matvec_t(tx)) { z = cgetg_copy(x, &lx); for (i=1; i vy) gel(z,2) = (lg(y) > 3)? gcopy(x): gen_0; gel(z,1) = gcopy(y); return z; } gel(z,1) = gcopy(y); if (is_const_t(tx)) { gel(z,2) = (lg(y) > 3)? gcopy(x): gmod(x,y); return z; } switch(tx) { case t_POL: case t_RFRAC: case t_SER: gel(z,2) = specialmod(x,y); return z; } } pari_err(operf,"%",x,y); return NULL; /* not reached */ } /*******************************************************************/ /* */ /* GENERIC EUCLIDEAN DIVISION */ /* */ /*******************************************************************/ GEN gdivent(GEN x, GEN y) { long tx = typ(x); 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 av1, av; long tx=typ(x),ty=typ(y); GEN q,r; int fl; 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 */ 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--) y[i] = 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(talker, "subst: unexpected variable precedence"); 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_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(typeer,"substpol"); 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(talker, "subst: unexpected variable precedence"); 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; if (tx == t_SER) { long V = valp(x); GEN y; lx = lg(x); if (lx == 2) return zeroser(v, V / d); y = ser2pol_i(x, lx); if (V % d != 0 || checkdeflate(y) % d != 0) pari_err(talker, "can't deflate this power series (d = %ld): %Ps", d, x); y = poltoser(RgX_deflate(y, d), v, 1 + (lx-3)/d); setvalp(y, V/d); return gerepilecopy(av, y); } /* t_POL */ if (checkdeflate(x) % d != 0) return NULL; return gerepilecopy(av, RgX_deflate(x,d)); } if (tx == t_RFRAC) { z = cgetg(3, t_RFRAC); gel(z,1) = gdeflate(gel(x,1),v,d); if (!z[1]) return NULL; gel(z,2) = gdeflate(gel(x,2),v,d); if (!z[2]) return NULL; return z; } if (is_matvec_t(tx)) { z = cgetg_copy(x, &lx); for (i=1; i= l-1) { d -= l-1; z = RgM_add(RgM_eval_powers(P,V,d+1,l-2), RgM_mul(z,gel(V,l))); z = gerepileupto(av, z); } z = RgM_add(RgM_eval_powers(P,V,0,d), RgM_mul(z,gel(V,d+2))); if (DEBUGLEVEL>=8) { long cnt = 1 + (degpol(P) - l) / (l-1); err_printf("RgX_RgMV_eval: %ld RgM_mul [%ld]\n", cnt, l-1); } return gerepileupto(av, z); } GEN RgX_RgM_eval(GEN Q, GEN x) { pari_sp av = avma; GEN z; long d = degpol(Q), rtd, n = lg(x)-1; if (d < 0) return zeromat(n, n); rtd = (long) sqrt((double)d); z = RgX_RgMV_eval(Q, RgM_powers(x, rtd)); return gerepileupto(av, z); } 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, e, 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 != lg(y[1])) pari_err(talker,"forbidden substitution by a non square matrix"); break; case t_QFR: case t_QFI: case t_VEC: case t_COL: pari_err(talker,"forbidden substitution by a vector"); break; /* not reached */ } if (is_scalar_t(tx)) { if (tx!=t_POLMOD || varncmp(v, varn(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(talker,"forbidden substitution in a scalar type"); 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): gcopy(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: ey = valp(y); vy = varn(y); if (ey < 1) return zeroser(vy, ey*(ex+lx-2)); if (lx == 2) return zeroser(vy, ey*ex); 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; } p2 = ex? gpowgs(y, ex): NULL; 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 (!p2) return gerepilecopy(av,z); return gerepileupto(av, gmul(z,p2)); case t_POL: if (lg(y) == 2) return (lx == 2)? gcopy(x): scalarser(gel(x,2),v,lx-2); case t_RFRAC: vy = gvar(y); e = gval(y,vy); if (e <= 0) pari_err(talker,"non positive valuation in a series substitution"); av = avma; p1 = poleval(ser2pol_i(x, lg(x)), y); z = gmul(gpowgs(y,ex), gadd(p1, zeroser(vy, e*(lx-2)))); return gerepileupto(av, z); default: pari_err(talker,"non polynomial or series type substituted in a series"); } 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=3 && gequal0(gel(x,mi))) mi--; u = cgetg(lx,t_SER); y = cgetg(lx,t_SER); u[1] = y[1] = evalsigne(1) | _evalvalp(1) | evalvarn(v); gel(u,2) = gel(y,2) = gen_1; if (lx > 3) { gel(u,3) = gmulsg(-2,gel(x,3)); gel(y,3) = gneg(gel(x,3)); } for (i=3; i1) pari_warn(warnmem,"recip"); for(k=i+1; k 0) return gen_0; if (varncmp(vx, v) == 0) return RgX_deriv(x); y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i 0) return gen_0; 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). We suppose x is a truc() */ if (signe(x) <= 0) pari_err(talker,"non-positive argument in O()"); if (!is_pm1(x)) return zeropadic(x,n); /* +/-1 = x^0 */ v = m = 0; break; case t_POL: if (!signe(x)) pari_err(talker,"zero argument in O()"); v = varn(x); if ((ulong)v > MAXVARN) pari_err(talker,"incorrect object in O()"); m = n * RgX_val(x); break; case t_RFRAC: if (!gequal0(gel(x,1))) pari_err(talker,"zero argument in O()"); v = gvar(x); if ((ulong)v > MAXVARN) pari_err(talker,"incorrect object in O()"); m = n * gval(x,v); break; default: pari_err(talker,"incorrect argument in O()"); 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 = cgetg(3,t_POLMOD); gel(y,1) = gcopy(gel(x,1)); gel(y,2) = integ(gel(x,2),v); return y; } if (gequal0(x)) return gen_0; return deg1pol(x, gen_0, v); } switch(tx) { case t_POL: vx = varn(x); lx = lg(x); if (lx == 2) { if (varncmp(vx, v) < 0) v = vx; return zeropol(v); } if (varncmp(vx, v) > 0) return deg1pol(x, gen_0, v); if (varncmp(vx, v) < 0) return triv_integ(x,v); y = cgetg(lx+1, t_POL); y[1] = x[1]; gel(y,2) = gen_0; for (i=3; i<=lx; i++) gel(y,i) = gdivgs(gel(x,i-1),i-2); return y; case t_SER: lx = lg(x); vx = varn(x); e = valp(x); if (lx == 2) { if (vx == v) e++; else if (varncmp(vx, v) < 0) v = vx; return zeroser(v, e); } if (varncmp(vx, v) > 0) { y = cgetg(4,t_POL); y[1] = evalvarn(v) | evalsigne(1); gel(y,2) = gen_0; gel(y,3) = gcopy(x); return y; } if (varncmp(vx, v) < 0) return triv_integ(x,v); y = cgetg(lx, t_SER); for (i=2; i 0) { y=cgetg(4,t_POL); y[1] = signe(x[1])? evalvarn(v) | evalsigne(1) : evalvarn(v); gel(y,2) = gen_0; gel(y,3) = gcopy(x); return y; } if (varncmp(vx, v) < 0) return gerepileupto(av, swapvar_act(x, vx, v, integ_act, NULL)); tx = typ(x[1]); i = is_scalar_t(tx)? 0: degpol(gel(x,1)); tx = typ(x[2]); n = is_scalar_t(tx)? 0: degpol(gel(x,2)); y = integ(gadd(x, zeroser(v,i+n + 2)), v); y = gdiv(gtrunc(gmul(gel(x,2), y)), gel(x,2)); if (!gequal(deriv(y,v),x)) pari_err(talker,"a log/atan appears in intformal"); if (typ(y)==t_RFRAC && lg(y[1]) == lg(y[2])) { GEN p2; tx=typ(y[1]); p1=is_scalar_t(tx)? gel(y,1): leading_term(gel(y,1)); tx=typ(y[2]); p2=is_scalar_t(tx)? gel(y,2): leading_term(gel(y,2)); y = gsub(y, gdiv(p1,p2)); } return gerepileupto(av,y); case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i=1; i 0) { cgiv(p1); return gerepileuptoint(av, addsi(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, lx, 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 */ lx = lg(x); e1 = expo(t) - bit_accuracy(lx) + 1; y = trunc2nr_lg(t, lx, 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) = gcopy(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(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; } lx = lg(x); e1 = e1 - bit_accuracy(lx) + 1; y = trunc2nr_lg(t, lx, 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(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) = gcopy(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(typeer,"grndtoi"); 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(typeer,"gtrunc2n"); return NULL; /* not reached */ } } /* e = number of error bits on integral part */ GEN gcvtoi(GEN x, long *e) { long tx = typ(x), lx, i, ex, e1; GEN y; if (tx == t_REAL) { ex = expo(x); if (ex < 0) { *e = ex; return gen_0; } lx = lg(x); e1 = ex - bit_accuracy(lx) + 1; y = trunc2nr_lg(x, lx, 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)) { 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(typeer,"isint"); 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)); } GEN gtrunc(GEN x) { long i, v; pari_sp av; 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: if (!signe(x[4])) return gen_0; v = valp(x); if (!v) return icopy(gel(x,4)); if (v>0) { /* here p^v is an integer */ av = avma; y = powiu(gel(x,2),v); return gerepileuptoint(av, mulii(y,gel(x,4))); } y = cgetg(3,t_FRAC); gel(y,1) = icopy(gel(x,4)); gel(y,2) = powiu(gel(x,2),-v); return y; case t_POL: return gcopy(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++) gel(x,i) = va_arg(ap, GEN); 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; } /* 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), lx, i, j; GEN y; if (v<0) v = 0; if (is_scalar_t(tx)) return scalarpol(x,v); switch(tx) { case t_POL: if (varncmp(varn(x), v) < 0) pari_err(talker,"variable must have higher priority in gtopoly"); y=gcopy(x); break; case t_SER: if (varncmp(varn(x), v) < 0) pari_err(talker,"variable must have higher priority in gtopoly"); y = ser2rfrac(x); if (typ(y) != t_POL) pari_err(talker,"t_SER with negative valuation in gtopoly"); break; case t_RFRAC: if (varncmp(varn(gel(x,2)), v) < 0) pari_err(talker,"variable must have higher priority in gtopoly"); y=gdeuc(gel(x,1),gel(x,2)); break; case t_QFR: case t_QFI: case t_VEC: case t_COL: case t_MAT: lx = lg(x); if (tx == t_QFR) lx--; if (varncmp(gvar(x), v) <= 0) pari_err(talker,"variable must have higher priority in gtopoly"); if (reverse) { /* cf normalizepol_lg */ for (i = lx-1; i>0; i--) if (! isrationalzero(gel(x,i))) break; if (i == 0) return zeropol(v); /* not a rational 0, to be kept iff all other coeffs are exact 0s */ y = gel(x,i); for (; i>0; i--) if (! isexactzero(gel(x,i))) break; if (i == 0) return scalarpol(y, v); for (j = i; j>0; j--) if (! gequal0(gel(x,j))) break; i += 2; y = cgetg(i,t_POL); y[1] = evalvarn(v) | evalsigne((j == 0)? 0: 1); for (j=2; j 0) return scalarser(x, v, prec); if (varncmp(vx, v) < 0) return coefstoser(x, v, prec); if (!lgpol(x)) return zeroser(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 poltoser(x, varn(x), precdl); case t_RFRAC: return rfractoser(x, gvar(x), precdl); } return NULL; } GEN gtoser(GEN x, long v, long prec) { long tx=typ(x), lx, 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(talker,"main variable must have higher priority in gtoser"); y = poltoser(x, v, prec); l = lg(y); for (i=2; i>1, i; for (i = 1; i <= lim; i++) swap(gel(y,i), gel(y,ly-i)); return y; } GEN gtocol(GEN x) { long lx, tx, i, j, h; GEN y; if (!x) return cgetg(1,t_COL); 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 = lg(x[1]); 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 gtovecsmall(GEN x) { GEN V; long tx, l,i; if (!x) return cgetg(1,t_VECSMALL); tx = typ(x); if (tx == t_VECSMALL) return gcopy(x); if (tx == t_INT) return mkvecsmall(itos(x)); if (tx == 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; } if (!is_vec_t(tx)) pari_err(typeer,"vectosmall"); l = lg(x); V = cgetg(l,t_VECSMALL); for(i=1; i= lx) pari_err(talker,"nonexistent component"); return stoi(x[n]); } pari_err(talker, "this object is a leaf. It has no components"); } if (n < 1) pari_err(talker,"nonexistent component"); if (tx == t_POL && (ulong)n+1 >= lx) return gen_0; if (tx == t_LIST) { long llx; x = list_data(x); llx = x? lg(x): 1; lx = (ulong)llx; tx = t_VEC; } l = (ulong)lontyp[tx] + (ulong)n-1; /* beware overflow */ if (l >= lx) pari_err(talker,"nonexistent component"); 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); return normalizepol_lg(z, lx); } /* 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 (w > v) 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(talker,"non existent component in truecoeff"); return gen_0; } if (v < 0 || v == (w=varn(x))) { if (N > dx) pari_err(talker,"non existent component in truecoeff"); return (N < 0)? gen_0: gel(x,N+2); } if (w > v) 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(typeer, "polcoeff"); 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 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 && n0)? icopy(gel(x,1)): negi(gel(x,1)); case t_POLMOD: av=avma; s=numer(gel(x,2)); tetpil=avma; return gerepile(av,tetpil,gmodulo(s,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; s=denom(x); tetpil=avma; return gerepile(av,tetpil,gmul(s,x)); } pari_err(typeer,"numer"); 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_REAL: return leafcopy(x); case t_INTMOD: return icopy(gel(x,2)); 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_FRAC: case t_FFELT: return gcopy(x); case t_PADIC: return gtrunc(x); case t_POL: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i=2; i--) gel(x,i) = lift_intern0(gel(x,i),v); return 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_intern0(gel(x,i),v); return x; } pari_err(typeer,"lift_intern"); return NULL; /* not reached */ } 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) { long i, 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: if (v < 0 || v == varn(gel(x,1))) return gcopy(gel(x,2)); y = cgetg(3, t_POLMOD); gel(y,1) = centerlift0(gel(x,1),v); gel(y,2) = centerlift0(gel(x,2),v); return y; case t_FRAC: return gcopy(x); case t_POL: case t_SER: 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; } pari_err(typeer,"centerlift"); return NULL; /* not reached */ } GEN centerlift(GEN x) { return centerlift0(x,-1); } /*******************************************************************/ /* */ /* 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 gand(GEN x, GEN y) { return gequal0(x)? gen_0: (gequal0(y)? gen_0: gen_1); } GEN gor(GEN x, GEN y) { return gequal0(x)? (gequal0(y)? gen_0: gen_1): 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 gcopy(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. x a ZV, don't use Horner */ static GEN qfeval0_Z(GEN q, GEN x, long l) { long i, j; pari_sp av = avma; GEN res; if (l == 2) return gerepileupto(av, gmul(gcoeff(q,1,1), sqri(gel(x,1)))); res = gmul(gcoeff(q,2,1), mulii(gel(x,2),gel(x,1))); /* i = 2 */ for (i=3;i 1. x a RgV, Horner-type evaluation */ static GEN qfeval0(GEN q, GEN x, long l) { long i, j; pari_sp av = avma; GEN res = gmul(gcoeff(q,1,1), gsqr(gel(x,1))); for (i=2; i 1. x a RgV */ static GEN hqfeval0(GEN q, GEN x, long l) { long i, j; pari_sp av = avma; GEN res, xc; if (l == 2) return gerepileupto(av, gmul(gcoeff(q,1,1), gnorm(gel(x,1)))); xc = gconj(x); res = 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.5.5/src/basemath/alglin1.c0000644000175000017500000023762012147140046015163 0ustar billbill/* $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. */ /********************************************************************/ /** **/ /** LINEAR ALGEBRA **/ /** (first part) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /* */ /* 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; if (! is_matvec_t(tx)) pari_err(typeer,"extract"); 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(talker,"mask too large in vecextract"); 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(talker, "incorrect range in extract"); 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=lx || j<=0) pari_err(talker,"no such component in vecextract"); gel(y,i) = gel(x,j); } return y; } if (tl == t_VECSMALL) { long ll=lg(L); y=cgetg(ll,tx); for (i=1; i=lx || j<=0) pari_err(talker,"no such component in vecextract"); gel(y,i) = gel(x,j); } return y; } pari_err(talker,"incorrect mask in vecextract"); 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) return y; av2 = avma; y = gcopy(y); } else { if (typ(x) != t_MAT) pari_err(typeer,"extract"); 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(lg(gel(x,1)), l1)) pari_err(talker,"incorrect mask in vecextract"); avma = av; return cgetg(1, t_MAT); } y = shallowextract(shallowtrans(y), l1); av2 = avma; y = gtrans(y); } stackdummy(av, av2); return y; } GEN genselect(void *E, long (*f)(void* E, GEN x), GEN A) { long i, l, nb = 0, t = typ(A); GEN B, v;/* v left on stack for efficiency */ pari_sp av; if (t == t_LIST) { GEN L; A = list_data(A); if (!A) return listcreate(); L = cgetg(3, t_LIST); l = lg(A); v = cgetg(l, t_VECSMALL); av = avma; for (i = 1; i < l; i++) { if (f(E, gel(A,i))) v[++nb] = i; avma = av; } B = cgetg(nb+1, t_VEC); for (i = 1; i <= nb; i++) gel(B, i) = gcopy(gel(A,v[i])); list_nmax(L) = nb; list_data(L) = B; return L; } else if (!is_matvec_t(t)) pari_err(typeer,"select"); l = lg(A); v = cgetg(l, t_VECSMALL); av = avma; for (i = 1; i < l; i++) { if (f(E, gel(A,i))) v[++nb] = i; avma = av; } B = cgetg(nb+1, t); for (i = 1; i <= nb; i++) gel(B, i) = gcopy(gel(A,v[i])); return B; } GEN select0(GEN f, GEN x) { if (typ(f) != t_CLOSURE || f[1] < 1) pari_err(typeer, "select"); return genselect((void *) f, gp_callbool, x); } GEN genapply(void *E, GEN (*f)(void* E, GEN x), GEN x) { long i, lx, tx = typ(x); GEN y; if (is_scalar_t(tx)) return f(E, x); switch(tx) { case t_POL: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i bit_accuracy(lg(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; } static GEN Fp_get_col(GEN a, GEN b, long li, GEN p) { GEN u = cgetg(li+1,t_COL); long i, j; gel(u,li) = Fp_mul(gel(b,li), gcoeff(a,li,li), p); for (i=li-1; i>0; i--) { pari_sp av = avma; GEN m = gel(b,i); for (j=i+1; j<=li; j++) m = subii(m, mulii(gcoeff(a,i,j), gel(u,j))); m = remii(m, p); gel(u,i) = gerepileuptoint(av, modii(mulii(m, gcoeff(a,i,i)), p)); } return u; } static GEN Fq_get_col(GEN a, GEN b, long li, GEN T, GEN p) { GEN u = cgetg(li+1,t_COL); long i, j; gel(u,li) = Fq_mul(gel(b,li), gcoeff(a,li,li), T,p); for (i=li-1; i>0; i--) { pari_sp av = avma; GEN m = gel(b,i); for (j=i+1; j<=li; j++) m = Fq_sub(m, Fq_mul(gcoeff(a,i,j), gel(u,j), T, p), NULL,p); m = Fq_red(m, T,p); gel(u,i) = gerepileupto(av, Fq_mul(m, gcoeff(a,i,i), T,p)); } return u; } /* assume 0 <= a[i,j] < p */ static uGEN Fl_get_col_OK(GEN a, uGEN b, long li, ulong p) { uGEN u = (uGEN)cgetg(li+1,t_VECSMALL); ulong m = b[li] % p; long i,j; u[li] = (m * ucoeff(a,li,li)) % p; for (i = li-1; i > 0; i--) { m = p - b[i]%p; for (j = i+1; j <= li; j++) { if (m & HIGHBIT) m %= p; m += ucoeff(a,i,j) * u[j]; /* 0 <= u[j] < p */ } m %= p; if (m) m = ((p-m) * ucoeff(a,i,i)) % p; u[i] = m; } return u; } static uGEN Fl_get_col(GEN a, uGEN b, long li, ulong p) { uGEN u = (uGEN)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 void /* same, reduce mod p */ _Fp_submul(GEN b, long k, long i, GEN m, GEN p) { if (lgefint(b[i]) > lgefint(p)) gel(b,i) = remii(gel(b,i), p); gel(b,k) = subii(gel(b,k), mulii(m, gel(b,i))); } static void /* same, reduce mod (T,p) */ _Fq_submul(GEN b, long k, long i, GEN m, GEN T, GEN p) { gel(b,i) = Fq_red(gel(b,i), T,p); gel(b,k) = gsub(gel(b,k), gmul(m, gel(b,i))); } static void /* assume m < p && SMALL_ULONG(p) && (! (b[i] & b[k] & HIGHMASK)) */ _Fl_submul_OK(uGEN b, long k, long i, ulong m, ulong p) { b[k] -= m * b[i]; if (b[k] & HIGHMASK) b[k] %= p; } static void /* assume m < p */ _Fl_submul(uGEN b, long k, long i, ulong m, ulong p) { b[i] %= p; b[k] = Fl_sub(b[k], Fl_mul(m, b[i], p), p); } static void /* same m = 1 */ _Fl_sub(uGEN b, long k, long i, ulong p) { b[k] = Fl_sub(b[k], b[i], p); } static void /* assume m < p && SMALL_ULONG(p) && (! (b[i] & b[k] & HIGHMASK)) */ _Fl_addmul_OK(uGEN b, long k, long i, ulong m, ulong p) { b[k] += m * b[i]; if (b[k] & HIGHMASK) b[k] %= p; } static void /* assume m < p */ _Fl_addmul(uGEN b, long k, long i, ulong m, ulong p) { b[i] %= p; b[k] = Fl_add(b[k], Fl_mul(m, b[i], p), p); } static void /* same m = 1 */ _Fl_add(uGEN b, long k, long i, ulong p) { b[k] = Fl_add(b[k], b[i], p); } 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(consister,"gauss"); *li = 0; return 0; } *li = lg(a[1])-1; if (*li < *aco) pari_err(mattype1,"gauss"); if (*b) { if (*li != *aco) pari_err(mattype1,"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(typeer,"gauss"); } if (lg((*b)[1])-1 != *li) pari_err(consister,"gauss"); } else *b = matid(*li); return 1; } static int is_modular_solve(GEN a, GEN b, GEN *u) { GEN p = NULL; if (!RgM_is_FpM(a, &p) || !p) return 0; a = RgM_to_FpM(a, p); if (!b) { a = FpM_inv(a,p); if (a) a = FpM_to_mod(a, p); } else { switch(typ(b)) { case t_COL: if (!RgV_is_FpV(b, &p)) return 0; b = RgC_to_FpC(b, p); a = FpM_gauss(a,b,p); if (a) a = FpC_to_mod(a, p); break; case t_MAT: if (!RgM_is_FpM(b, &p)) return 0; b = RgM_to_FpM(b, p); a = FpM_gauss(a,b,p); if (a) a = FpM_to_mod(a, p); break; default: return 0; } } *u = a; return 1; } /* Gaussan Elimination. Compute a^(-1)*b * b is a matrix or column vector, NULL meaning: take the identity matrix * If a and b are empty, the result is the empty matrix. * * li: nb lines of a and b * aco: nb columns of a * bco: nb columns of b (if matrix) * * li > aco is allowed if b = NULL, in which case return c such that c a = Id */ 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 (!init_gauss(a, &b, &aco, &li, &iscol)) return cgetg(1, iscol?t_COL:t_MAT); pivot = get_pivot_fun(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; } 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; 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 = 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 (m == 1) { for (j=i+1; j<=aco; j++) _Fl_sub((uGEN)a[j],k,i, p); for (j=1; j<=bco; j++) _Fl_sub((uGEN)b[j],k,i, p); } else if (OK_ulong) { for (j=i+1; j<=aco; j++) _Fl_submul_OK((uGEN)a[j],k,i,m, p); for (j=1; j<=bco; j++) _Fl_submul_OK((uGEN)b[j],k,i,m, p); } else { for (j=i+1; j<=aco; j++) _Fl_submul((uGEN)a[j],k,i,m, p); for (j=1; j<=bco; j++) _Fl_submul((uGEN)b[j],k,i,m, p); } } } u = cgetg(bco+1,t_MAT); if (OK_ulong) for (j=1; j<=bco; j++) ugel(u,j) = Fl_get_col_OK(a,(uGEN)b[j], aco,p); else for (j=1; j<=bco; j++) ugel(u,j) = Fl_get_col(a,(uGEN)b[j], aco,p); return u; } GEN matid_Flm(long n) { GEN y = cgetg(n+1,t_MAT); long i; if (n < 0) pari_err(talker,"negative size in matid_Flm"); for (i=1; i<=n; i++) { gel(y,i) = const_vecsmall(n, 0); ucoeff(y, i,i) = 1; } return y; } GEN Flm_gauss(GEN a, GEN b, ulong p) { return Flm_gauss_sp(RgM_shallowcopy(a), RgM_shallowcopy(b), p); } static GEN Flm_inv_sp(GEN a, ulong p) { return Flm_gauss_sp(a, matid_Flm(lg(a)-1), p); } GEN Flm_inv(GEN a, ulong p) { return Flm_inv_sp(RgM_shallowcopy(a), p); } GEN FpM_gauss(GEN a, GEN b, GEN p) { pari_sp av = avma, lim; long i, j, k, li, bco, aco; int iscol; GEN u; if (!init_gauss(a, &b, &aco, &li, &iscol)) return cgetg(1, iscol?t_COL:t_MAT); if (lgefint(p) == 3) { ulong pp = (ulong)p[2]; a = ZM_to_Flm(a, pp); b = ZM_to_Flm(b, pp); u = Flm_gauss_sp(a,b, pp); if (!u) {avma = av; return u;} u = iscol? Flc_to_ZC(gel(u,1)): Flm_to_ZM(u); return gerepileupto(av, u); } lim = stack_lim(av,1); a = RgM_shallowcopy(a); bco = lg(b)-1; for (i=1; i<=aco; i++) { GEN invpiv; for (k = i; k <= li; k++) { GEN piv = remii(gcoeff(a,k,i), p); if (signe(piv)) { gcoeff(a,k,i) = Fp_inv(piv, p); break; } gcoeff(a,k,i) = gen_0; } /* 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 = remii(gcoeff(a,k,i), p); gcoeff(a,k,i) = gen_0; if (!signe(m)) continue; m = Fp_mul(m, invpiv, p); for (j=i+1; j<=aco; j++) _Fp_submul(gel(a,j),k,i,m, p); for (j=1 ; j<=bco; j++) _Fp_submul(gel(b,j),k,i,m, p); } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"FpM_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) = Fp_get_col(a, gel(b,j), aco, p); return gerepilecopy(av, iscol? gel(u,1): u); } GEN FqM_gauss(GEN a, GEN b, GEN T, GEN p) { pari_sp av = avma, lim; long i, j, k, li, bco, aco = lg(a)-1; int iscol; GEN u; if (!T) return FpM_gauss(a,b,p); if (!init_gauss(a, &b, &aco, &li, &iscol)) return cgetg(1, iscol?t_COL:t_MAT); lim = stack_lim(av,1); a = RgM_shallowcopy(a); bco = lg(b)-1; for (i=1; i<=aco; i++) { GEN invpiv; for (k = i; k <= li; k++) { GEN piv = Fq_red(gcoeff(a,k,i), T,p); if (signe(piv)) { gcoeff(a,k,i) = Fq_inv(piv,T,p); break; } gcoeff(a,k,i) = gen_0; } /* 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 */ for (k=i+1; k<=li; k++) { GEN m = Fq_red(gcoeff(a,k,i), T,p); gcoeff(a,k,i) = gen_0; if (!signe(m)) continue; m = Fq_mul(m, invpiv, T,p); for (j=i+1; j<=aco; j++) _Fq_submul(gel(a,j),k,i,m, T,p); for (j=1; j<=bco; j++) _Fq_submul(gel(b,j),k,i,m, T,p); } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"FpM_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) = Fq_get_col(a, gel(b,j), aco, T, p); return gerepilecopy(av, iscol? gel(u,1): u); } GEN FpM_inv(GEN x, GEN p) { return FpM_gauss(x, NULL, p); } /* 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; byteptr d; long lM = lg(M), stable = 0; if (lM == 1) return cgetg(1,t_MAT); if (!dM) dM = det(M); if (is_pm1(dM)) dM = NULL; av2 = avma; H = NULL; d = init_modular(&p); for(;;) { NEXT_PRIME_VIADIFF_CHECK(p,d); if (dM) { ulong dMp = umodiu(dM,p); if (!dMp) continue; Hp = Flm_inv_sp(ZM_to_Flm(M,p), p); if (dMp != 1) Flm_Fl_mul_inplace(Hp, dMp, p); } else Hp = Flm_inv_sp(ZM_to_Flm(M,p), p); if (!H) { H = ZM_init_CRT(Hp, p); q = utoipos(p); } else { GEN qp = muliu(q,p); stable = ZM_incremental_CRT(&H, Hp, q,qp, p); q = qp; } if (DEBUGLEVEL>5) err_printf("inverse mod %ld (stable=%ld)", p,stable); if (stable) {/* DONE ? */ if (dM) { 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 (DEBUGLEVEL>5) err_printf("ZM_inv done"); 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(typeer,"detint"); 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 = lg(A[1]) - 1; if (n < m) return gen_0; c = const_vecsmall(m, 0); 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; } 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; } } #define COPY(x) {\ GEN _t = (x); if (!is_universal_constant(_t)) x = gcopy(_t); \ } static void gerepile_gauss_ker(GEN x, long k, long t, pari_sp av) { pari_sp tetpil = avma; long u,i, n = lg(x)-1, m = n? lg(x[1])-1: 0; if (DEBUGMEM > 1) pari_warn(warnmem,"gauss_pivot_ker. k=%ld, n=%ld",k,n); for (u=t+1; u<=m; u++) COPY(gcoeff(x,u,k)); for (i=k+1; i<=n; i++) for (u=1; u<=m; u++) COPY(gcoeff(x,u,i)); gerepile_mat(av,tetpil,x,k,m,n,t); } static void gerepile_gauss_FpM_ker(GEN x, GEN p, long k, long t, pari_sp av) { pari_sp tetpil = avma; long u,i, n = lg(x)-1, m = n? lg(x[1])-1: 0; if (DEBUGMEM > 1) pari_warn(warnmem,"gauss_pivot_ker. k=%ld, n=%ld",k,n); for (u=t+1; u<=m; u++) if (isonstack(gcoeff(x,u,k))) gcoeff(x,u,k) = modii(gcoeff(x,u,k),p); for (i=k+1; i<=n; i++) for (u=1; u<=m; u++) if (isonstack(gcoeff(x,u,i))) gcoeff(x,u,i) = modii(gcoeff(x,u,i),p); gerepile_mat(av,tetpil,x,k,m,n,t); } /* special gerepile for huge matrices */ 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? lg(x[1])-1: 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; } } /* 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 = lg(x[1])-1; pp = cgetg(n+1,t_COL); x = RgM_shallowcopy(x); c = const_vecsmall(m, 0); 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; d[k] = ck[i]; c[i] = k; l[k] = i; /* pivot d[k] in x[i,k] */ } if (k > nc) { avma = av; return zerocol(nc); } if (k == 1) { avma = av; return scalarcol_shallow(gen_1,nc); } y = cgetg(nc+1,t_COL); gel(y,1) = gel(ck, l[1]); for (D=gel(d,1),j=2; 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 GEN gauss_pivot(GEN x, long *rr) { GEN data; pivot_fun pivot = get_pivot_fun(x, &data); return RgM_pivots(x, data, rr, pivot); } /* compute ker(x) */ static GEN ker_aux(GEN x) { pari_sp av = avma; GEN d,y; long i,j,k,r,n; x = gauss_pivot_ker(x,&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 0 for all j, but why take chances? */ for (k = j = 1; j<=rx; j++) if (d[j]) { c[ d[j] ] = 1; y[k++] = x[j]; } for (j=1; j<=n; j++) if (!c[j]) y[k++] = j; avma = av; rx -= r; for (j=1; j<=rx; j++) gel(y,j) = gcopy(gel(y,j)); for ( ; j<=n; j++) gel(y,j) = col_ei(n, y[j]); return y; } static GEN FpM_gauss_pivot(GEN x, GEN p, long *rr); static GEN FqM_gauss_pivot(GEN x, GEN T, GEN p, long *rr); static GEN Flm_gauss_pivot(GEN x, ulong p, long *rr); static void init_suppl(GEN x) { if (lg(x) == 1) pari_err(talker,"empty matrix in suppl"); /* HACK: avoid overwriting d from gauss_pivot() after avma=av */ (void)new_chunk(lg(x[1]) * 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(typeer,"suppl"); if (RgM_is_FpM(x, &p) && p) return gerepileupto(av, FpM_to_mod(FpM_suppl(RgM_to_FpM(x, p), p), p)); avma = av; init_suppl(x); d = gauss_pivot(X,&r); avma = av; return get_suppl(X,d,r); } 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,r); } 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,r); } GEN image2(GEN x) { pari_sp av = avma; long k, n, i; GEN A, B; if (typ(x)!=t_MAT) pari_err(typeer,"image2"); 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(flagerr,"matimage"); } return NULL; /* not reached */ } long rank(GEN x) { pari_sp av = avma; long r; GEN p = NULL; if (typ(x)!=t_MAT) pari_err(typeer,"rank"); if (RgM_is_FpM(x, &p) && p) { r = FpM_rank(RgM_to_FpM(x, p), p); avma = av; return r; } (void)gauss_pivot(x, &r); avma = av; return lg(x)-1 - r; } GEN Flm_indexrank(GEN x, ulong p) { long i,j,r; GEN res,d,p1,p2; pari_sp av = avma; long n = lg(x)-1; (void)new_chunk(3+n+1+n+1); /* yield r = dim ker(x) */ d = Flm_gauss_pivot(x,p,&r); avma = av; /* now r = dim Im(x) */ r = n - r; res=cgetg(3,t_VEC); 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 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; } 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(typeer,"indexrank"); if (RgM_is_FpM(x, &p) && p) return gerepileupto(av, FpM_indexrank(RgM_to_FpM(x, p), p)); init_indexrank(x); 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); } /*******************************************************************/ /* */ /* LINEAR ALGEBRA MODULO P */ /* */ /*******************************************************************/ /* in place, destroy x */ GEN F2m_ker_sp(GEN x, long deplin) { GEN y, c, d; long i, j, k, r, m, n; n = lg(x)-1; m = mael(x,1,1); r=0; c = const_vecsmall(m, 0); d = new_chunk(n+1); for (k=1; k<=n; k++) { for (j=1; j<=m; j++) if (!c[j] && F2m_coeff(x,j,k)) break; if (j > m) { if (deplin) { GEN c = zero_F2v(n); for (i=1; i m) { if (deplin) { c = cgetg(n+1, t_VECSMALL); for (i=1; im) { if (deplin) { c = cgetg(n+1, t_COL); 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); for (k=i+1; k<=nbco; k++) { ulong m = ucoeff(a,i,k); if (!m) continue; m = Fl_div(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; } GEN FpM_det(GEN a, GEN p) { pari_sp av = avma, lim = stack_lim(av,1); long i,j,k, s = 1, nbco = lg(a)-1; GEN q, x = gen_1; if (lgefint(p) == 3) { ulong d, pp = (ulong)p[2]; if (pp==2) d = F2m_det_sp(ZM_to_F2m(a)); else d = Flm_det_sp(ZM_to_Flm(a, pp), pp); avma = av; return utoi(d); } a = RgM_shallowcopy(a); for (i=1; i nbco) return gerepileuptoint(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 = Fp_mul(x,q,p); for (k=i+1; k<=nbco; k++) { GEN m = modii(gcoeff(a,i,k), p); if (!signe(m)) continue; m = Fp_div(m, q, p); for (j=i+1; j<=nbco; j++) { gcoeff(a,j,k) = Fp_sub(gcoeff(a,j,k), Fp_mul(m,gcoeff(a,j,i),p),p); if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"det. col = %ld",i); gerepileall(av,2, &a,&x); q = gcoeff(a,i,i); m = gcoeff(a,i,k); m = Fp_div(m, q, p); } } } } if (s < 0) x = gneg_i(x); return gerepileuptoint(av, Fp_mul(x, gcoeff(a,nbco,nbco),p)); } 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=lg(x[1])-1; r=0; d=cgetg(n+1,t_VECSMALL); x = Flm_copy(x); c = const_vecsmall(m, 0); 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 x, GEN p, long *rr) { pari_sp av, lim; GEN c, d; long i, j, k, r, t, m, n = lg(x)-1; if (!n) { *rr = 0; return NULL; } if (lgefint(p) == 3) { ulong pp = (ulong)p[2]; return Flm_gauss_pivot(ZM_to_Flm(x, pp), pp, rr); } m=lg(x[1])-1; r=0; d = cgetg(n+1, t_VECSMALL); x = RgM_shallowcopy(x); c = const_vecsmall(m, 0); 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) = modii(gcoeff(x,j,k), p); if (signe(gcoeff(x,j,k))) break; } if (j>m) { r++; d[k]=0; } else { GEN piv = Fp_inv(gcoeff(x,j,k), p); togglesign(piv); c[j] = k; d[k] = j; for (i=k+1; i<=n; i++) gcoeff(x,j,i) = Fp_mul(piv,gcoeff(x,j,i), p); for (t=1; t<=m; t++) { if (c[t]) continue; /* already a pivot on that line */ piv = modii(gcoeff(x,t,k), p); if (!signe(piv)) continue; gcoeff(x,t,k) = gen_0; for (i=k+1; i<=n; i++) gcoeff(x,t,i) = addii(gcoeff(x,t,i), mulii(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) = gen_0; /* dummy */ } } *rr = r; avma = (pari_sp)d; return d; } static GEN FqM_gauss_pivot(GEN x, GEN T, GEN p, long *rr) { pari_sp av, lim; GEN c, d; long i, j, k, r, t, n, m; n=lg(x)-1; if (!n) { *rr=0; return NULL; } m=lg(x[1])-1; r=0; d = cgetg(n+1, t_VECSMALL); x = RgM_shallowcopy(x); c = const_vecsmall(m, 0); 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) = Fq_red(gcoeff(x,j,k), T,p); if (signe(gcoeff(x,j,k))) break; } if (j>m) { r++; d[k]=0; } else { GEN piv = gneg(Fq_inv(gcoeff(x,j,k), T,p)); c[j]=k; d[k]=j; for (i=k+1; i<=n; i++) gcoeff(x,j,i) = Fq_mul(piv,gcoeff(x,j,i), T, p); for (t=1; t<=m; t++) { if (c[t]) continue; /* already a pivot on that line */ piv = Fq_red(gcoeff(x,t,k), T,p); if (!signe(piv)) continue; gcoeff(x,t,k) = gen_0; for (i=k+1; i<=n; i++) gcoeff(x,t,i) = gadd(gcoeff(x,t,i), gmul(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) = gen_0; /* dummy */ } } *rr=r; return d; } GEN FpM_image(GEN x, GEN p) { pari_sp av = avma; GEN d, y; long j, k, r; d = FpM_gauss_pivot(x,p,&r); if (!d) { avma = av; return ZM_copy(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++) = ZC_copy(gel(x,k)); return y; } 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; } GEN Flm_image(GEN x, ulong p) { pari_sp av = avma; GEN d,y; long j,k,r; d = Flm_gauss_pivot(x,p,&r); if (!d) { avma = av; return Flm_copy(x); } /* d left on stack */ 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++) = Flv_copy(gel(x,k)); return y; } long Flm_rank(GEN x, ulong p) { pari_sp av = avma; long r; (void)Flm_gauss_pivot(x,p,&r); avma = av; return lg(x)-1 - r; } static GEN sFpM_invimage(GEN mat, GEN y, GEN p) { pari_sp av = avma; long i, l = lg(mat); GEN M = cgetg(l+1,t_MAT), col, t; if (l==1) return NULL; if (lg(y) != lg(mat[1])) pari_err(consister,"FpM_invimage"); for (i=1; i 1) pari_warn(warnmem,"gauss_pivot_ker. k=%ld, n=%ld",k,n); for (u=t+1; u<=m; u++) if (isonstack(gcoeff(x,u,k))) gcoeff(x,u,k) = Fq_red(gcoeff(x,u,k),T,p); for (i=k+1; i<=n; i++) for (u=1; u<=m; u++) if (isonstack(gcoeff(x,u,i))) gcoeff(x,u,i) = Fq_red(gcoeff(x,u,i),T,p); gerepile_mat(av,tetpil,x,k,m,n,t); } static void Flxq_gerepile_gauss_ker(GEN x, GEN T, ulong p, long k, long t, pari_sp av) { pari_sp tetpil = avma; long u,i, n = lg(x)-1, m = n? lg(x[1])-1: 0; if (DEBUGMEM > 1) pari_warn(warnmem,"gauss_pivot_ker. k=%ld, n=%ld",k,n); for (u=t+1; u<=m; u++) if (isonstack(gcoeff(x,u,k))) gcoeff(x,u,k) = Flx_rem(gcoeff(x,u,k),T,p); for (i=k+1; i<=n; i++) for (u=1; u<=m; u++) if (isonstack(gcoeff(x,u,i))) gcoeff(x,u,i) = Flx_rem(gcoeff(x,u,i),T,p); gerepile_mat(av,tetpil,x,k,m,n,t); } static GEN FqM_ker_i(GEN x, GEN T, GEN p, long deplin) { pari_sp av0, av, lim, tetpil; GEN y, c, d; long i, j, k, r, t, n, m; if (!T) return FpM_ker_i(x,p,deplin); n=lg(x)-1; if (!n) 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 = ZX_to_Flx(T,l); GEN p1 = FlxM_to_ZXM(FlxqM_ker(Ml,Tl,l)); return gerepileupto(ltop,p1); } m=lg(x[1])-1; r=0; av0 = avma; x = RgM_shallowcopy(x); c = const_vecsmall(m, 0); 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) = Fq_red(gcoeff(x,j,k), T, p); if (signe(gcoeff(x,j,k))) break; } if (j>m) { if (deplin) { c = cgetg(n+1, t_COL); for (i=1; im) { if (deplin) { c = cgetg(n+1, t_COL); for (i=1; i n) pari_err(talker, "missing eigenspace. Compute the matrix to higher accuracy, then restart eigen at the current precision"); 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,1))) { 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 nbco = lg(a)-1; if (typ(a)!=t_MAT) pari_err(mattype1,"det2"); if (!nbco) return gen_1; if (nbco != lg(a[1])-1) pari_err(mattype1,"det2"); pivot = get_pivot_fun(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: { 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))); } } 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) { GEN s = NULL; long k; bound /= (lbest-1); 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) { GEN s = NULL; long k; bound /= (lbest-1); 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); } GEN det(GEN a) { long n = lg(a)-1; double B; GEN data, p=NULL; pivot_fun pivot; if (typ(a)!=t_MAT) pari_err(mattype1,"det"); if (!n) return gen_1; if (n != lg(a[1])-1) pari_err(mattype1,"det"); if (n == 1) return gcopy(gcoeff(a,1,1)); if (RgM_is_FpM(a, &p) && p) { pari_sp av = avma; return gerepilecopy(av, Fp_to_mod(FpM_det(RgM_to_FpM(a, p), p), p)); } pivot = get_pivot_fun(a, &data); if (pivot != gauss_get_pivot_NZ) return det_simple_gauss(a, data, pivot); B = (double)n; B = B*B; B = B*B; return det_develop(a, 7, B); } /* 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(typeer,"gaussmodulo"); lM = lg(M); if (lM == 1) { if ((typ(Y)!=t_INT && lg(Y)!=1) || (typ(D)!=t_INT && lg(D)!=1)) pari_err(consister,"gaussmodulo"); if (ptu1) *ptu1 = cgetg(1, t_MAT); return gen_0; } n = lg(M[1])-1; switch(typ(D)) { case t_COL: if (lg(D)-1!=n) pari_err(consister,"gaussmodulo"); delta = diagonal_shallow(D); break; case t_INT: delta = scalarmat_shallow(D,n); break; default: pari_err(typeer,"gaussmodulo"); 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(consister,"gaussmodulo"); break; default: pari_err(typeer,"gaussmodulo"); 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.5.5/src/basemath/FF.c0000644000175000017500000004516512147140046014130 0ustar billbill/* $Id$ 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 (x[1]!=y[1] || !equalii(gel(x,4),gel(y,4)) || !gequal(gel(x,3),gel(y,3))) pari_err(operi,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 x[1] == y[1] && equalii(gel(x,4),gel(y,4)) && gidentical(gel(x,3),gel(y,3)) && 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_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)); } } 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(gdiver); 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(gdiver); 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(talker,"nth-root does not exist in FF_sqrtn"); (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_sqrtn(gel(x,2),gen_2,T,p,NULL); break; case t_FF_F2xq: r=F2xq_sqrt(gel(x,2),T); break; default: r=Flxq_sqrtn(gel(x,2),gen_2,T,pp,NULL); } if (!r) pari_err(talker,"squareroot does not exist in FF_sqrt"); 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 (!K) pari_err(talker,"missing exponent in FF_ispower"); 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); if (!r) { avma = av; return 0; } break; case t_FF_F2xq: r = F2xq_sqrtn(gel(x,2),K,T,NULL); if (!r) { avma = av; return 0; } break; default: /* case t_FF_Flxq: */ r = Flxq_sqrtn(gel(x,2),K,T,pp,NULL); if (!r) { avma = av; return 0; } break; } 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; 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(talker,"inconsistent moduli in Rg_to_Fp: %Ps, %Ps", q, p); return remii(a, p); } default: pari_err(typeer, "Rg_to_Fp"); return NULL; /* not reached */ } } ulong Rg_to_Fl(GEN x, ulong p) { switch(typ(x)) { case t_INT: return umodiu(x, p); case t_FRAC: { ulong z = umodiu(gel(x,1), p); if (!z) return 0; return Fl_div(z, umodiu(gel(x,2), p), p); } case t_PADIC: return padic_to_Fl(x, p); case t_INTMOD: { GEN q = gel(x,1), a = gel(x,2); if (equaliu(q, p)) return itou(a); if (!dvdiu(q,p)) pari_err(talker,"inconsistent moduli in Rg_to_Fp: %Ps, %lu", q, p); return umodiu(a, p); } default: pari_err(typeer, "Rg_to_Fl"); return 0; /* 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 Rg_to_Fp(a, p); 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(typeer,"Rg_to_FpXQ"); 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 normalizepol_lg(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 RgX_to_FpXQX(GEN x, GEN T, GEN p) { long i, l = lg(x); GEN z = cgetg(l, t_POL); z[1] = x[1]; for (i = 2; i < l; i++) gel(z,i) = Rg_to_FpXQ(gel(x,i), T,p); return normalizepol_lg(z, l); } GEN RgX_to_FqX(GEN x, GEN T, GEN p) { long i, l = lg(x); GEN z = cgetg(l, t_POL); z[1] = x[1]; for (i = 2; i < l; i++) gel(z,i) = simplify_shallow(Rg_to_FpXQ(gel(x,i), T,p)); return normalizepol_lg(z, l); } /* lg(V) > 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=d ) return d; pr=n*d; if (pr<=1) return 1; r=d/sqrt(pr); c=(long)ceil(d/ceil(r)); f=(long)floor(d/floor(r)); return (brent_kung_nbmul(d, n, c) <= brent_kung_nbmul(d, n, f))?c:f; } #endif /*Return optimal parameter l for the evaluation of n polynomials of degree d*/ long brent_kung_optpow(long d, long n) { long l, pr; if (n >= d) return d; pr = n*d; if (pr <= 1) return 1; l = (long) ((double)d / sqrt(pr)); return (d+l-1) / l; } /*Close to FpXV_FpC_mul*/ static GEN FpXQ_eval_powers(GEN P, GEN V, long a, long n, GEN p) { GEN z = scalar_ZX_shallow(gel(P,2+a), varn(P)); /* V[1] = 1 */ long i; for (i=1; i<=n; i++) z = ZX_add(z, ZX_Z_mul(gel(V,i+1),gel(P,2+a+i))); return FpX_red(z, p); } /* 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 FpX_FpXQV_eval(GEN P, GEN V, GEN T, GEN p) { pari_sp av = avma, btop; long l = lg(V)-1, d = degpol(P); GEN z, u; if (d < 0) return pol_0(varn(T)); if (d < l) { z = FpXQ_eval_powers(P,V,0,d,p); return gerepileupto(av, z); } if (l<=1) pari_err(talker,"powers is only [] or [1] in FpX_FpXQV_eval"); d -= l; btop = avma; z = FpXQ_eval_powers(P,V,d+1,l-1,p); while (d >= l-1) { d -= l-1; u = FpXQ_eval_powers(P,V,d+1,l-2,p); z = FpX_add(u, FpXQ_mul(z,gel(V,l),T,p), p); z = gerepileupto(btop, z); } u = FpXQ_eval_powers(P,V,0,d,p); z = FpX_add(u, FpXQ_mul(z,gel(V,d+2),T,p), p); if (DEBUGLEVEL>=8) { long cnt = 1 + (degpol(P) - l) / (l-1); err_printf("FpX_FpXQV_eval: %ld FpXQ_mul [%ld]\n", cnt, l-1); } return gerepileupto(av, z); } /* Q in Z[X] and x in Fp[X]/(T). Return a lift of Q(x) */ GEN FpX_FpXQ_eval(GEN Q, GEN x, GEN T, GEN p) { pari_sp av = avma; GEN z; long d = degpol(Q), rtd; if (d < 0) return pol_0(varn(Q)); rtd = (long) sqrt((double)d); z = FpX_FpXQV_eval(Q, FpXQ_powers(x,rtd,T,p), T,p); return gerepileupto(av, z); } 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, gmul(p1,y)); } r = (i==j)? y: Fq_pow(y, utoipos(i-j+1), T, p); p1 = Fq_red(gadd(gmul(p1,r), gel(x,j)), T, p); } return gerepileupto(av, p1); } /*******************************************************************/ /* */ /* FpXX */ /* */ /*******************************************************************/ /*Polynomials whose coefficients are either polynomials or integers*/ 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) { ulong pp = (ulong)p[2]; GEN Pl, Ql, Tl, U; Pl = ZXX_to_FlxX(P, pp, varn(T)); Ql = ZXX_to_FlxX(Q, pp, varn(T)); Tl = ZX_to_Flx(T, pp); 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) { ulong pp = (ulong)p[2]; GEN Pl, Ql, Tl, Dl; Pl = ZXX_to_FlxX(x, pp, varn(T)); Ql = ZXX_to_FlxX(y, pp, varn(T)); Tl = ZX_to_Flx(T, pp); 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 = FqX_divrem(d,d1,T,p, &r); v = FqX_sub(v, FqX_mul(q,v1, T,p), T,p); u=v; v=v1; v1=u; u=r; d=d1; d1=u; } if (ptu) *ptu = FqX_div(FqX_sub(d, FqX_mul(b,v, T,p), T,p),a, T,p); *ptv = v; } gerepileall(ltop,ptu?3:2,&d,ptv,ptu); return d; } /* 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(gdiver); 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)); } /*******************************************************************/ /* */ /* (Fp[X]/T(X))[Y] / S(Y) */ /* */ /*******************************************************************/ /*Preliminary implementation to speed up FpX_ffisom*/ typedef struct { GEN S, T, p; } FpXYQQ_muldata; /* reduce x in Fp[X, Y] in the algebra Fp[X, Y]/ (P(X),Q(Y)) */ static GEN FpXYQQ_redswap(GEN x, GEN S, GEN T, GEN p) { pari_sp ltop=avma; long n=degpol(S); long m=degpol(T); long v=varn(T),w=varn(S); GEN V = RgXY_swap(x,n,w); setvarn(T,w); V = FpXQX_red(V,T,p); setvarn(T,v); V = RgXY_swap(V,m,w); return gerepilecopy(ltop,V); } static GEN FpXYQQ_sqr(void *data, GEN x) { FpXYQQ_muldata *D = (FpXYQQ_muldata*)data; return FpXYQQ_redswap(FpXQX_sqr(x, D->S, 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->S, 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 = p[2]; x = ZXX_to_FlxX(x, pp, varn(T)); S = ZX_to_Flx(S, pp); T = ZX_to_Flx(T, 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) { GEN kx = mod_to_Kronecker(x, T); GEN ky = mod_to_Kronecker(y, T); GEN t = Kronecker_to_FpXQX(ZX_mul(kx, ky), T, p); return FpXQX_rem(t, S, T, p); } GEN FpXQXQ_sqr(GEN x, GEN S, GEN T, GEN p) { GEN kx = mod_to_Kronecker(x, T); GEN t = Kronecker_to_FpXQX(ZX_sqr(kx), T, p); return FpXQX_rem(t, S, T, p); } typedef struct { GEN T, p, S; } kronecker_muldata; static GEN _FpXQXQ_red(void *data, GEN x) { kronecker_muldata *D = (kronecker_muldata*)data; GEN t = Kronecker_to_FpXQX(x, D->T, D->p); t = FpXQX_rem(t, D->S, D->T, D->p); return mod_to_Kronecker(t, D->T); } static GEN _FpXQXQ_mul(void *data, GEN x, GEN y) { return _FpXQXQ_red(data, ZX_mul(x,y)); } static GEN _FpXQXQ_sqr(void *data, GEN x) { return _FpXQXQ_red(data, ZX_sqr(x)); } /* 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; kronecker_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): gcopy(x); if (lgefint(p) == 3) { ulong pp = p[2]; GEN z; long v = varn(T); T = ZX_to_Flx(T, pp); x = ZXX_to_FlxX(x, pp, v); S = ZXX_to_FlxX(S, pp, v); 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(mod_to_Kronecker(x,T), n, (void*)&D,&_FpXQXQ_sqr,&_FpXQXQ_mul); y = Kronecker_to_FpXQX(y, T,p); } return gerepileupto(ltop, y); } /*******************************************************************/ /* */ /* Fq */ /* */ /*******************************************************************/ GEN Fq_add(GEN x, GEN y, GEN T/*unused*/, GEN p) { (void)T; switch((typ(x)==t_POL)|((typ(y)==t_POL)<<1)) { case 0: return Fp_add(x,y,p); case 1: return FpX_Fp_add(x,y,p); case 2: return FpX_Fp_add(y,x,p); case 3: return FpX_add(x,y,p); } return NULL; } GEN Fq_sub(GEN x, GEN y, GEN T/*unused*/, GEN p) { (void)T; switch((typ(x)==t_POL)|((typ(y)==t_POL)<<1)) { case 0: return Fp_sub(x,y,p); case 1: return FpX_Fp_sub(x,y,p); case 2: return Fp_FpX_sub(x,y,p); case 3: return FpX_sub(x,y,p); } return NULL; } GEN Fq_neg(GEN x, GEN T/*unused*/, GEN p) { (void)T; return (typ(x)==t_POL)? FpX_neg(x,p) : Fp_neg(x,p); } /* If T==NULL do not reduce*/ GEN Fq_mul(GEN x, GEN y, GEN T, GEN p) { switch((typ(x)==t_POL)|((typ(y)==t_POL)<<1)) { case 0: return Fp_mul(x,y,p); case 1: return FpX_Fp_mul(x,y,p); case 2: return FpX_Fp_mul(y,x,p); case 3: if (T) return FpXQ_mul(x,y,T,p); else return FpX_mul(x,y,p); } return NULL; } /* y t_INT */ GEN Fq_Fp_mul(GEN x, GEN y, GEN T/*unused*/, GEN p) { (void)T; return (typ(x) == t_POL)? FpX_Fp_mul(x,y,p) : Fp_mul(x,y,p); } /* If T==NULL do not reduce*/ GEN Fq_sqr(GEN x, GEN T, GEN p) { if (typ(x) == t_POL) { if (T) return FpXQ_sqr(x,T,p); else return FpX_sqr(x,p); } else return Fp_sqr(x,p); return NULL; } GEN Fq_neg_inv(GEN x, GEN T, GEN p) { if (typ(x) == t_INT) return Fp_inv(Fp_neg(x,p),p); return FpXQ_inv(FpX_neg(x,p),T,p); } GEN Fq_invsafe(GEN x, GEN pol, GEN p) { if (typ(x) == t_INT) return Fp_invsafe(x,p); return FpXQ_invsafe(x,pol,p); } GEN Fq_inv(GEN x, GEN pol, GEN p) { if (typ(x) == t_INT) return Fp_inv(x,p); return FpXQ_inv(x,pol,p); } GEN Fq_pow(GEN x, GEN n, GEN pol, GEN p) { if (typ(x) == t_INT) return Fp_pow(x,n,p); return FpXQ_pow(x,n,pol,p); } GEN Fq_sqrt(GEN x, GEN T, GEN p) { if (typ(x) == t_POL) return FpXQ_sqrtn(x,gen_2,T,p,NULL); else return Fp_sqrt(x,p); return NULL; } /*******************************************************************/ /* */ /* Fq[X] */ /* */ /*******************************************************************/ /* 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; if (!signe(P) || !signe(c)) return gcopy(P); /* signe works for t_(INT|POL) */ 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, normalizepol(Q)); } 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 = ZX_to_Flx(T, pp); GEN Vl = ZXXV_to_FlxXV(V, pp, varn(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); } } 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); if (lgefint(l)==3) { ulong p = l[2]; GEN M, V = Flm_Frobenius(ZM_to_Flm(MA, p), r, p, evalvarn(vu)); if (DEBUGLEVEL>=4) timer_printf(&T,"pol[Frobenius]"); M = FlxqV_Flx_Frobenius(V, ZX_to_Flx(U, p), ZX_to_Flx(P, p), p); if (DEBUGLEVEL>=4) timer_printf(&T,"U[Frobenius]"); if (p==2) A = F2m_to_ZM(F2m_ker(Flm_to_F2m(M))); else A = Flm_to_ZM(Flm_ker(M,p)); } else { GEN 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(talker,"ZZ_%Ps[%Ps]/(%Ps) is not a field in FpX_ffintersect" ,l,pol_x(vp),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); R = shallowtrans(R); for(i=1;i 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; ulong t; (void)u_lvalrem(pg, 2, &t); /* 2 implicit in pgener_Fp_local */ z = pgener_Fp_local(l, gel(Z_factor(utoipos(t)), 1)); z = Fp_pow(z, diviuexact(subis(l,1), pg), l); /* prim. pg-th root of 1 */ z = negi(z); if (DEBUGLEVEL>=4) timer_start(&T); A = FpM_ker(RgM_Rg_add_shallow(MA, z),l); if (lg(A)!=2) pari_err(talker,"ZZ_%Ps[%Ps]/(%Ps) is not a field in FpX_ffintersect" ,l,pol_x(vp),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(talker,"ZZ_%Ps[%Ps]/(%Ps) is not a field in FpX_ffintersect" ,l,pol_x(vq),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 (!invmod(Bn,l,&z)) pari_err(talker,"Polynomials not irreducible in FpX_ffintersect"); z = Fp_mul(An,z,l); L = Fp_sqrtn(z,ipg,l,NULL); if ( !L ) pari_err(talker,"Polynomials not irreducible in FpX_ffintersect"); 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 = intersect_ker(P, MA, U, l); B = intersect_ker(Q, MB, U, l); if (DEBUGLEVEL>=4) timer_start(&T); An = gel(FpXYQQ_pow(A,ipg,U,P,l),2); Bn = gel(FpXYQQ_pow(B,ipg,U,Q,l),2); if (DEBUGLEVEL>=4) timer_printf(&T,"pows [P,Q]"); z = Fq_inv(Bn,U,l); z = Fq_mul(An,z,U,l); if (typ(z)==t_INT) z = scalarpol(z,MAXVARN); L = FpXQ_sqrtn(z,ipg,U,l,NULL); if (DEBUGLEVEL>=4) timer_printf(&T,"FpXQ_sqrtn"); if (!L) pari_err(talker,"Polynomials not irreducible in FpX_ffintersect"); B = FqX_Fq_mul(B,L,U,l); B = gsubst(B,MAXVARN,gen_0); A = gsubst(A,MAXVARN,gen_0); } } if (e) { GEN VP, VQ, Ay, By, lmun = addis(l,-1); long i, 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 RgY : * Q a RgY of degree n, P(X) = sum P_i * X^i, where the deg P_i are t_POLMOD * mod Q or RgY of degree < n. * Lift the P_i which are t_POLMOD, then return subst(P( Y^(2n-1) ), Y,X) */ GEN mod_to_Kronecker(GEN P, GEN Q) { long i, k, lx = lg(P), N = (degpol(Q)<<1) + 1, vQ = varn(Q); GEN y = cgetg((N-2)*(lx-2) + 2, t_POL); for (k=i=2; i 0) { gel(y,k++) = c; j = 3; } else { long l = lg(c); for (j=2; j < l; j++) gel(y,k++) = gel(c,j); } if (i == lx-1) break; for ( ; j < N; j++) gel(y,k++) = gen_0; } y[1] = P[1]; setlg(y, k); return y; } /*******************************************************************/ /* */ /* MODULAR GCD */ /* */ /*******************************************************************/ /* return z = a mod q, b mod p (p,q) = 1. qinv = 1/q mod p */ static GEN Fl_chinese_coprime(GEN a, ulong b, GEN q, ulong p, ulong qinv, GEN pq) { ulong d, amod = umodiu(a, p); pari_sp av = avma; GEN ax; if (b == amod) return NULL; d = (b > 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 = lg(Hp[1]), 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; } return stable; } int ZX_incremental_CRT(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 ZM_incremental_CRT(GEN *pH, GEN Hp, GEN q, GEN qp, ulong p) { GEN h, H = *pH, lim = shifti(qp,-1); ulong qinv = Fl_inv(umodiu(q,p), p); long i,j, l = lg(H), m = lg(H[1]); int stable = 1; for (j=1; j 0) h = subii(h,qp); gcoeff(H,i,j) = h; stable = 0; } } 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); } da = db; /* = degpol(a) */ 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"); if (!P) avma = av; else 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--) 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)); } 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) 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 = poldegree(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; } } /* check that theta(maxprime) - theta(27448) >= 2^bound */ /* NB: theta(27449) ~ 27225.387, theta(x) > 0.98 x for x>7481 * (Schoenfeld, 1976 for x > 1155901 + direct calculations) */ static void check_theta(ulong bound) { maxprime_check( (ulong)ceil((bound * LOG2 + 27225.388) / 0.98) ); } /* 27449 = prime(3000) */ byteptr init_modular(ulong *p) { *p = 27449; return diffptr + 3000; } /* 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; 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; byteptr d = init_modular(&p); dglist = Hp = H0p = H1p = C0 = C1 = NULL; /* gcc -Wall */ if (LERS) { if (!checksqfree) pari_err(talker,"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 */ while (p < (ulong)(dres<<1)) NEXT_PRIME_VIADIFF(p,d); 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); check_theta(bound); dp = 1; for(;;) { NEXT_PRIME_VIADIFF_CHECK(p,d); 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 { GEN qp = muliu(q,p); stable = ZX_incremental_CRT(&H, Hp, q,qp, p); if (LERS) { stable &= ZX_incremental_CRT(&H0,H0p, q,qp, p); stable &= ZX_incremental_CRT(&H1,H1p, q,qp, p); } q = qp; } /* could make it probabilistic for H ? [e.g if stable twice, etc] * Probabilistic anyway for H0, H1 */ if (DEBUGLEVEL>5) err_printf("resultant mod %ld (bound 2^%ld, stable=%ld)", p,expi(q),stable); 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); } } END: 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; int stable; GEN q, a, b, H; byteptr d; if ((H = trivial_case(A,B)) || (H = trivial_case(B,A))) return H; q = H = NULL; av2 = avma; lim = stack_lim(av,2); 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 ); for(cnt = 1; cnt < CNTMAX; cnt++, prec = (prec-1)<<1) { GEN R = fp_resultant(RgX_gtofp(A, prec), RgX_gtofp(B, prec)); bnd = gexpo(R) + 1; if (bnd >= 0 && bnd <= (long)bound && !gequal0(R)) break; } if (cnt < CNTMAX) bound = bnd; if (dB) bound -= (long)(dbllog2(dB)*degA); } } if (DEBUGLEVEL>4) err_printf("bound for resultant: 2^%ld\n",bound); d = init_modular(&p); check_theta(bound); dp = 1; /* denominator mod p */ for(;;) { long dropa, dropb; NEXT_PRIME_VIADIFF_CHECK(p,d); 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] */ { GEN qp = muliu(q,p); stable = Z_incremental_CRT(&H, Hp, q,qp, p); q = qp; } if (DEBUGLEVEL>5) err_printf("resultant mod %ld (bound 2^%ld, stable = %d)",p,expi(q),stable); 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); } } 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); byteptr d; 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] */ av2 = avma; U = NULL; d = init_modular(&p); for(;;) { GEN a, b, qp, Up, Vp; int stable; NEXT_PRIME_VIADIFF_CHECK(p,d); 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(&U, Up, q,qp, p); stable&= ZX_incremental_CRT(&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); } } 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(talker,"non positive degree in ffinit"); if (typ(p) != t_INT) pari_err(typeer, "ffinit"); if (signe(p) <= 0) pari_err(talker,"%Ps is not a prime", 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)); } pari-2.5.5/src/basemath/bit.c0000644000175000017500000002433112147140046014403 0ustar billbill/* $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. */ #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: { GEN xp=int_MSW(x); lx=lgefint(x); if (lx==2) return mkvec(gen_0); ly = BITS_IN_LONG+1; m=HIGHBIT; u=*xp; while (!(m & u)) { m>>=1; ly--; } y = cgetg(ly + bit_accuracy(lx-1), t_VEC); ly=1; 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_accuracy(lx)) pari_err(precer,"binary"); p1 = cgetg(maxss(ex,0)+2,t_VEC); p2 = cgetg(bit_accuracy(lx)-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 lgefint(x)) return 0; return (*int_W(x,q) >> r) & 1; } GEN gbittest(GEN x, long n) { return map_proto_lGL(bittest,x,n); } /***********************************************************************/ /** **/ /** BITMAP OPS **/ /** x & y (and), x | y (or), x ^ y (xor), ~x (neg), x & ~y (negimply) **/ /** **/ /***********************************************************************/ /* Truncate a non-negative integer to a number of bits. */ static GEN ibittrunc(GEN x, long bits) { long lowbits, known_zero_words, xl = lgefint(x) - 2; long len_out = nbits2nlong(bits); if (xl < len_out) return x; /* Check whether mask is trivial */ lowbits = bits & (BITS_IN_LONG-1); if (!lowbits) { if (xl == len_out) return x; } else if (len_out <= xl) { GEN xi = int_W(x, len_out-1); /* Non-trival mask is given by a formula, if x is not normalized, this works even in the exceptional case */ *xi &= (1L << lowbits) - 1; if (*xi && xl == len_out) return x; } /* Normalize */ known_zero_words = xl - len_out; if (known_zero_words < 0) known_zero_words = 0; return int_normalize(x, known_zero_words); } GEN gbitneg(GEN x, long bits) { const ulong uzero = 0; long lowbits, xl, len_out, i; if (typ(x) != t_INT) pari_err(typeer, "bitwise negation"); if (bits < -1) pari_err(talker, "negative exponent in bitwise negation"); if (bits == -1) return inegate(x); if (bits == 0) return gen_0; if (signe(x) < 0) { /* Consider as if mod big power of 2 */ pari_sp ltop = avma; return gerepileuptoint(ltop, ibittrunc(inegate(x), bits)); } xl = lgefint(x); len_out = nbits2prec(bits); lowbits = bits & (BITS_IN_LONG-1); if (len_out > 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)) GEN gbitor(GEN x, GEN y) { pari_sp ltop = avma; GEN z; if (typ(x) != t_INT || typ(y) != t_INT) pari_err(typeer, "bitwise or"); 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; case 0: /*-1,-1*/ z = ibitand(inegate(x),inegate(y)); break; default: return NULL; } return gerepileuptoint(ltop, inegate(z)); } GEN gbitand(GEN x, GEN y) { pari_sp ltop = avma; GEN z; if (typ(x) != t_INT || typ(y) != t_INT) pari_err(typeer, "bitwise and"); 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; case 0: /*-1,-1*/ z = inegate(ibitor(inegate(x),inegate(y))); break; default: return NULL; } return gerepileuptoint(ltop, z); } GEN gbitxor(GEN x, GEN y) { pari_sp ltop = avma; GEN z; if (typ(x) != t_INT || typ(y) != t_INT) pari_err(typeer, "bitwise xor"); 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; case 0: /*-1,-1*/ z = ibitxor(inegate(x),inegate(y)); break; default: return NULL; } return gerepileuptoint(ltop,z); } /* x & ~y */ GEN gbitnegimply(GEN x, GEN y) { pari_sp ltop = avma; GEN z; if (typ(x) != t_INT || typ(y) != t_INT) pari_err(typeer, "bitwise negated imply"); 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; case 0: /*-1,-1*/ z = ibitnegimply(inegate(y),inegate(x)); break; default: return NULL; } return gerepileuptoint(ltop,z); } pari-2.5.5/src/basemath/subcyclo.c0000644000175000017500000006723212147140046015457 0ustar billbill/* $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. */ #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 = group_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); if (DEBUGLEVEL >= 6) timer_printf(&ti, "polsubcyclo_cyclic"); 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= 1) timer_start(&ti); l = n+1; e = 1; while(!uisprime(l)) { l += n; e++; } if (DEBUGLEVEL >= 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: borne=%Ps\n",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); if (DEBUGLEVEL >= 1) timer_printf(&ti, "Zp_sqrtnlift"); *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) = exp_Ir(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(talker,"bnr must be over Q in bnr_to_znstar"); /* 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(flagerr,"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(talker,"degree <= 0 in galoissubcyclo"); break; case t_VEC: if (lg(N)==7) N = bnr_to_znstar(N,&complex); if (lg(N)==4) { GEN gen = gel(N,3); Z = N; if (typ(gen)!=t_VEC) pari_err(typeer,"galoissubcyclo"); if (lg(gen) == 1) n = 1; else { GEN z = gel(gen,1); if (typ(z) != t_INTMOD) #ifdef NETHACK_MESSAGES pari_err(talker,"You have transgressed!"); #else pari_err(talker,"Please do not try to break PARI with ridiculous counterfeit data. Thanks!"); #endif n = itos(gel(z,1)); } break; } default: /*fall through*/ pari_err(typeer,"galoissubcyclo"); 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 = group_order(H); phi_n = eulerphiu(n); if (card == phi_n) { avma = ltop; if (flag==3) return galoiscyclo(n,v); 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,3); L = polsubcyclo_orbits(n,H,O,powz,NULL); B = polsubcyclo_complex_bound(av,L,3); 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). n = p^a primary and d | phi(n) = (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 (v<0) v = 0; if (d==1) return deg1pol_shallow(gen_1,gen_m1,v); if (d<=0 || n<=0) pari_err(typeer,"polsubcyclo"); if ((n & 3) == 2) n >>= 1; if (n == 1 || d >= n) pari_err(talker,"degree does not divide phi(n) in polsubcyclo"); 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,3); L = polsubcyclo_cyclic(n,d,o,g,gd,powz,NULL); B = polsubcyclo_complex_bound(ltop,L,3); zl = polsubcyclo_start(n,d,o,B,&val,&l); le = gel(zl,1); if (DEBUGLEVEL >= 6) timer_start(&ti); 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 = znstar(stoi(n)); /* polsubcyclo_g is twice faster but Z must be cyclic */ if (lg(Z[2]) == 2 && dvdis(gel(Z,1), d)) { 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 = stackmalloc(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 = stackmalloc(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, 3)); 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(talker,"non-positive degree in factor_Aurifeuille"); 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.5.5/src/basemath/base2.c0000644000175000017500000026045512147140046014632 0ustar billbill/* $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. */ /*******************************************************************/ /* */ /* MAXIMAL ORDERS */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" /* FIXME: backward compatibility. Should use the proper nf_* equivalents */ #define compat_PARTIAL 1 #define compat_ROUND2 2 static void nfmaxord_check_args(nfmaxord_t *S, GEN T, long flag, GEN fa) { GEN dT, P; long l; if (typ(T)!=t_POL) pari_err(notpoler,"nfmaxord"); if (degpol(T) <= 0) pari_err(constpoler,"nfmaxord"); if (fa) { if (typ(fa) != t_MAT) pari_err(typeer,"nfmaxord"); dT = factorback(fa); if (!signe(dT)) pari_err(talker,"reducible polynomial in nfmaxord"); } else { dT = ZX_disc(T); if (flag & nf_PARTIALFACT) fa = Z_factor_limit(absi(dT), 0); else fa = Z_factor(absi(dT)); } S->dT = dT; P = gel(fa,1); l = lg(P); if (l > 1 && is_pm1(gel(P,1))) P = vecslice(P, 2, --l); S->dTP = P; S->dTE = vec_to_vecsmall(gel(fa,2)); } static int fnz(GEN x,long j) { long i; for (i=1; i 0) d = t; } return d; } static void allbase_from_ordmax(nfmaxord_t *S, GEN ordmax, GEN P, GEN f) { GEN a = NULL, da = NULL, index, P2, E2, D; long n = degpol(f), lP = lg(P), i, j, k; int centered = 0; for (i=1; i5) err_printf("Result for prime %Ps is:\n%Ps\n",P[i],b); } if (da) { index = diviiexact(da, gcoeff(a,1,1)); for (j=2; j<=n; j++) index = mulii(index, diviiexact(da, gcoeff(a,j,j))); if (!centered) a = ZM_hnfcenter(a); a = RgM_Rg_div(a, da); } else { index = gen_1; a = matid(n); } S->dK = 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)); } /*******************************************************************/ /* */ /* 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 q,j,k,pro, c = lg(a), r = lg(a[1]); 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)); } /* Input: * x normalized integral polynomial of degree n, defining K=Q(theta). * * code 0, 1 or (long)p if we want base, smallbase ou factoredbase (resp.). * y is GEN *, which will receive the discriminant of K. * * Output * 1) A t_COL whose n components are rationnal polynomials (with degree * 0,1...n-1) : integral basis for K (putting x=theta). * Rem: common denominator is in da. * * 2) discriminant of K (in *y). */ static void allbase2(nfmaxord_t *S, GEN f) { GEN cf, ordmax, P = S->dTP, E = S->dTE; 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)); ordmax = cgetg(lP, t_VEC); for (i=1; idTP; lP = lg(P); E = S->dTE; ordmax = cgetg(1, t_VEC); for (i=1; idT; 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); } RETRY { if (DEBUGLEVEL) err_printf("Treating p^k = %Ps^%ld\n",P[i],E[i]); ordmax = shallowconcat(ordmax, mkvec( maxord(gel(P,i),T,E[i]) )); } ENDCATCH; } allbase_from_ordmax(S, ordmax, P, T); } /* d a t_INT, f a t_MAT factorisation sharing some prime divisors with d */ static GEN update_fact(GEN d, GEN f) { GEN fa, E, Q, P = gel(f,1); long iq, i, k, l; if (typ(f)!=t_MAT || lg(f)!=3) pari_err(talker,"not a factorisation in nfbasis"); l = lg(P); if (l > 1 && is_pm1(gel(P,1))) P = vecslice(P, 2, --l); Q = cgetg(l,t_COL); E = cgetg(l,t_COL); iq = 1; for (i=1; i2) { err_printf(" dedek: gcd has degree %ld\n", dk); if (DEBUGLEVEL>5) err_printf("initial parameters p=%Ps,\n f=%Ps\n",p,f); } if (2*dk >= mf-1) return FpX_div(f,k,p); return dk? NULL: f; } /* p-maximal order of Af; mf = v_p(Disc(f)) */ static GEN maxord(GEN p,GEN f,long mf) { const pari_sp av = avma; GEN w = NULL, g, res, fp = FpX_red(f, p); if (cmpui(degpol(f),p) < 0) g = FpX_div(fp, FpX_gcd(fp,ZX_deriv(fp), p), p); else { w = gel(FpX_factor(fp,p),1); g = FpXV_prod(w, p); } res = dedek(f, mf, p, g); if (res) res = dbasis(p, f, mf, pol_x(varn(f)), res); else { if (!w) w = gel(FpX_factor(fp,p),1); res = maxord_i(p, f, mf, w, 0); } return gerepileupto(av,res); } /* Sylvester's matrix, mod p^m (assumes f1 monic) */ static GEN ZpX_sylvester_hnf(GEN f1, GEN f2, 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 ZM_hnfmodall(a, pm, hnf_MODID|hnf_PART); } /* polynomial gcd mod p^m (assumes f1 monic) */ GEN ZpX_gcd(GEN f1, GEN f2, GEN pm) { pari_sp av = avma; GEN a = ZpX_sylvester_hnf(f1,f2,pm); long c, l = lg(a), v = varn(f1); for (c = 1; c < l; c++) { GEN t = gcoeff(a,c,c); if (!equalii(t, pm)) return gerepileupto(av, RgX_Rg_div(RgV_to_RgX(gel(a,c), v), t)); } avma = av; return pol_0(v); } /* Return m > 0, such that p^m ~ 2^32 for initial value of m; p > 1 */ static long init_m(GEN p) { if (lgefint(p) > 3) return 1; return (long)(32 / log2(p[2])); } /* reduced resultant mod p^m (assumes x monic) */ GEN ZpX_reduced_resultant(GEN x, GEN y, GEN pm) { pari_sp av = avma; GEN z = ZpX_sylvester_hnf(x,y,pm); z = gcoeff(z,1,1); if (equalii(z,pm)) { avma = av; return gen_0; } return gerepileuptoint(av, icopy(z)); } /* 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, q); if (signe(R)) return R; } q = powiu(p, M); R = ZpX_reduced_resultant(f,g, q); return signe(R)? R: q; } /* discriminant valuation mod p^m (assumes x monic, dx = x') */ static long ZpX_disc_val_i(GEN x, GEN dx, GEN p, GEN pm) { pari_sp av = avma; GEN z = ZpX_sylvester_hnf(x,dx,pm); long i, v = 0, l = lg(z); for (i = 1; i < l; i++) { GEN c = gcoeff(z,i,i); if (equalii(c, pm)) { avma = av; return -1; } /* failure */ v += Z_pval(c, p); } return v; } /* assume f monic */ long ZpX_disc_val(GEN f, GEN p) { pari_sp av = avma; GEN q = NULL, df; long v, m; if (degpol(f) == 1) return 0; df = ZX_deriv(f); m = init_m(p); if (m < 2) m = 2; for(;; m <<= 1) { q = q? sqri(q): powiu(p, m); /* p^m */ v = ZpX_disc_val_i(f,df, p, q); if (v >= 0) break; } 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; D = gpowgs(p, vD); 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; } static GEN dbasis(GEN p, GEN f, long mf, GEN a, GEN U) { long n = degpol(f), dU, i, vda; GEN D, da, b, ha, pd, pdp; if (n == 1) return scalarmat(gen_1, 1); if (DEBUGLEVEL>5) { err_printf(" entering Dedekind Basis with parameters p=%Ps\n",p); err_printf(" f = %Ps,\n a = %Ps\n",f,a); } pd = powiu(p, mf >> 1); pdp = mulii(pd,p); dU = U ? degpol(U): 0; b = cgetg(n, t_MAT); /* Z[a] + U/p Z[a] is maximal */ ha = scalarpol(pd, varn(f)); a = QpX_remove_denom(a, p, &da, &vda); D = da? mulii(pdp, da): pdp; /* skip first column = [pd, 0,...,0] */ for (i=1; i>1) - 1); else { ha = FpXQ_mul(ha, a, f, D); if (da) ha = ZX_Z_divexact(ha, da); } gel(b,i) = RgX_to_RgV(ha,n); } b = ZM_hnfmodid(b,pd); if (DEBUGLEVEL>5) err_printf(" new order: %Ps\n",b); return RgM_Rg_div(b, pd); } static GEN get_partial_order_as_pols(GEN p, GEN f) { long v = ZpX_disc_val(f, p); return RgM_to_RgXV(maxord(p,f, v), varn(f)); } typedef struct __decomp { /* constants */ GEN p, f; /* goal: factor f p-adically */ long df; /* p^df = reduced discriminant of f */ 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, precns; /* cached Newton sums and their precision */ } decomp_t; /* 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, res, pr, pk, ph, b1, b2, a, e, de, f1, f2, dt, th; GEN p = S->p; 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"); } if (!FpX_valrem(S->chi, S->nu, p, &b1)) pari_err(talker, "bug in Decomp (not a factor), is p = %Ps a prime?", p); b2 = FpX_div(S->chi, 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), 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, Dov2, d1, d2, ib1, ib2; long n, n1, n2, i; gerepileall(av, 4, &f1, &f2, &e, &de); D = de; ib1 = get_partial_order_as_pols(p,f1); n1 = lg(ib1)-1; ib2 = get_partial_order_as_pols(p,f2); n2 = lg(ib2)-1; n = n1+n2; d1 = QpXV_denom(ib1); d2 = QpXV_denom(ib2); if (cmpii(d1, d2) < 0) d1 = d2; if (d1 != gen_1) { ib1 = Q_muli_to_int(ib1, d1); ib2 = Q_muli_to_int(ib2, d1); D = mulii(d1, D); } Dov2 = shifti(D,-1); fred = centermod_i(S->f, D, Dov2); res = cgetg(n+1, t_VEC); for (i=1; i<=n1; i++) gel(res,i) = FpX_center(FpX_rem(FpX_mul(gel(ib1,i),e,D), fred, D), D, Dov2); e = Z_ZX_sub(de, e); ib2 -= n1; for ( ; i<=n; i++) gel(res,i) = FpX_center(FpX_rem(FpX_mul(gel(ib2,i),e,D), fred, D), D, Dov2); res = RgXV_to_RgM(res, n); return RgM_Rg_div(ZM_hnfmodid(res,D), D); /* normalized integral basis */ } } /* 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; } } 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)); t = gmax(t, pp); if (! S->precns || cmpii(S->precns, t) < 0) { if (DEBUGLEVEL>4) err_printf(" Precision for cached Newton sums: %Ps -> %Ps\n", S->precns? S->precns: gen_0, t); 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-1); 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 of S->phi mod (p, S->chi) */ static long factcp(decomp_t *S) { GEN chi = mycaract(S, S->chi, S->phi, S->psf, S->prc); long l; S->chi = chi; S->nu = get_nu(chi, S->p, &l); return l; } /* Return the prime element in Zp[phi], a t_INT (iff *Ep = 1) or QX; * nup, chip are ZX. * 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 chin, q, qp; long r, s; 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_pow(nup, utoipos(r), S->chi, qp); if (!phi) return RgX_Rg_div(nup, q); /* phi = X : no composition */ return compmod(S->p, nup, phi, S->chi, qp, -s); } static void kill_cache(decomp_t *S) { S->precns = NULL; } /* S->phi := T o T0 mod (p, f) */ static void composemod(decomp_t *S, GEN T, GEN T0) { S->phi = compmod(S->p, T, T0, S->f, S->p, 0); } static int update_phi(decomp_t *S, long *ptl, long flag) { GEN PHI = NULL, prc, psc = S->psc, X = pol_x(varn(S->f)); GEN pdf = powiu(S->p, S->df); long k; if (!S->chi) { kill_cache(S); S->chi = mycaract(S, S->f, S->phi, S->psf, pdf); S->nu = get_nu(S->chi, S->p, ptl); if (*ptl > 1) return 0; /* we can get a decomposition */ } for (k = 1;; k++) { kill_cache(S); 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->phi0? compmod(S->p, S->phi, S->phi0, S->f, S->psc, 0) : S->phi; PHI = gadd(PHI, ZX_Z_mul(X, mului(k, S->p))); S->chi = mycaract(S, S->f, PHI, S->psc, pdf); } psc = mulii(sqri(prc), S->p); S->chi = FpX_red(S->chi, psc); if (!PHI) /* ok above for k = 1 */ PHI = S->phi0? compmod(S->p, S->phi, S->phi0, S->f, psc, 0) : S->phi; S->phi = PHI; if (is_pm1(prc)) { /* may happen if p is unramified */ if (!flag) { *ptl = 1; return 0; } S->nu = get_nu(S->chi, S->p, ptl); 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 can be split * 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, chi0 = S->chi; if (DEBUGLEVEL>4) err_printf(" Increasing Fa\n"); for (;;) { S->phi = gadd(theta, random_FpX(dlim, v, S->p)); /* phi non-primary ? */ if (factcp(S) > 1) { composemod(S, S->phi, T0); return 1; } if (degpol(S->nu) == D) break; S->chi = chi0; } S->phi0 = T0; return 0; /* F_phi=lcm(F_alpha, F_theta)=D and E_phi=E_alpha */ } /* 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, 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); } S->phi = RgX_add(c, pol_x(varn(S->chi))); if (factcp(S) > 1) { composemod(S, S->phi, T0); return 1; } S->phi0 = T0; return 0; /* E_phi = lcm(E_alpha,E_theta) */ } static GEN ch_var(GEN x, long v) { if (typ(x) == t_POL) { x = leafcopy(x); setvarn(x, v); } return x; } /* 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 = gadd(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_pow(S->invnu, stoi(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; } /* return 1 if at least 2 factors mod p ==> chi can be split */ static int loop(decomp_t *S, long nv, long Ea, long Fa) { pari_sp av2 = avma, limit = stack_lim(av2, 1); GEN R, w, chib, beta, gamm, chig, nug, delt = NULL; long L, E, i, l, Fg, eq = 0, er = 0, N = degpol(S->f), v = varn(S->f); beta = FpXQ_pow(S->nu, stoi(Ea), S->chi, S->p); S->invnu = NULL; chib = chig = NULL; /* -Wall */ for (;;) { /* beta tends to a factor of chi */ if (DEBUGLEVEL>4) err_printf(" beta = %Ps\n", beta); R = modii(ZX_resultant(beta, S->chi), S->pmf); if (signe(R)) { chib = NULL; L = Z_pval(R, S->p); E = N; } else { /* pmf | norm(beta) ==> useless */ chib = ZXQ_charpoly(beta, S->chi, v); vstar(S->p, chib, &L, &E); } eq = (long)(L / E); er = (long)(L*Ea / E - eq*Ea); if (DEBUGLEVEL>4) err_printf(" (eq,er) = (%ld,%ld)\n", eq,er); if (er || !chib) { /* gamm might not be an integer ==> chig = NULL */ gamm = get_gamma(S, beta, eq, er); /* = beta p^-eq nu^-er (a unit) */ chig = mycaract(S, S->chi, gamm, S->psc, S->prc); } else { /* gamm = beta/p^eq, special case of the above */ GEN h = powiu(S->p, eq); gamm = RgX_Rg_div(beta, h); chig = RgX_Rg_div(RgX_unscale(chib, h), powiu(h, N)); chig = gequal1(Q_denom(chig))? FpX_red(chig, S->pmf): NULL; } if (!chig) { /* Valuation of beta was wrong ==> gamma fails the v*-test */ chib = ZXQ_charpoly(beta, S->chi, v); vstar(S->p, chib, &L, &E); eq = (long)(L / E); er = (long)(L*Ea / E - eq*Ea); gamm = get_gamma(S, beta, eq, er); /* an integer */ chig = mycaract(S, S->chi, gamm, S->psc, S->prc); } nug = get_nu(chig, S->p, &l); if (l > 1) { S->chi = chig; S->nu = nug; composemod(S, gamm, S->phi); return 1; } Fg = degpol(nug); if (Fa % Fg) return testb2(S, clcm(Fa,Fg), gamm); /* nug irreducible mod p */ w = FpX_factorff_irred(nug, ch_var(S->nu, nv), S->p); if (degpol(gel(w,1)) != 1) pari_err(talker, "no root in nilord. Is p = %Ps a prime?", S->p); for (i = 1; i < lg(w); i++) { /* Look for a root delt of nug in Fp[phi] such that vp(gamma - delta) > 0 Can be used to improve beta */ GEN eta, chie, nue, W = gel(w,i); /* monic linear polynomial */ delt = gneg_i( ch_var(gel(W,2), v) ); eta = gsub(gamm, delt); if (typ(delt) == t_INT) chie = RgX_translate(chig, delt); /* frequent special case */ else { if (!dvdii(QXQ_intnorm(eta, S->chi), S->p)) continue; chie = mycaract(S, S->chi, eta, S->psc, S->prc); } nue = get_nu(chie, S->p, &l); if (l > 1) { S->nu = nue; S->chi= chie; composemod(S, eta, S->phi); return 1; } if (RgX_is_monomial(nue)) { /* vp(eta) = vp(gamma - delta) > 0 */ long Le, Ee; GEN pie; if (dvdii(constant_term(chie), S->psc)) { chie = mycaract(S, S->chi, eta, S->pmf, S->prc); if (dvdii(constant_term(chie), S->pmf)) chie = ZXQ_charpoly(eta, S->chi, v); } pie = getprime(S, eta, chie, nue, &Le, &Ee, 0,Ea); if (pie) return testc2(S, S->nu, Ea, pie, Ee); break; } } if (i == lg(w)) pari_err(talker, "no root in nilord. Is p = %Ps a prime?", S->p); if (eq) delt = gmul(delt, powiu(S->p, eq)); if (er) delt = gmul(delt, gpowgs(S->nu, er)); beta = gsub(beta, delt); if (low_stack(limit,stack_lim(av2,1))) { if (DEBUGMEM > 1) pari_warn(warnmem, "nilord"); gerepileall(av2, S->invnu? 5: 3, &beta, &(S->precns), &(S->ns), &(S->invnu), &(S->Dinvnu)); } } } /* 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 mf, long flag) { GEN p = S->p; long Fa, oE, l, N = degpol(S->f), v = varn(S->f), nv = fetch_var(); 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, mf+1); S->precns = NULL; oE = 0; opa = NULL; /* -Wall */ l = 2; /* Decomp by default */ for(;;) { S->phi0 = NULL; /* no delayed composition */ Fa = degpol(S->nu); for(;;) { long 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 = (Ea > 1)? 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); S->chi = NULL; if (!update_phi(S, &l, flag)) goto DONE; if (pia) break; } if (DEBUGLEVEL>4) err_printf(" (Fa, oE) = (%ld,%ld)\n", Fa, oE); if (oE*Fa == N) { /* O = Zp[phi] */ if (!flag) S->phi = redelt(S->phi, sqri(p), p); S->chi = NULL; l = 1; goto DONE; } l = 2; if (loop(S, nv, oE, Fa)) goto DONE; if (!update_phi(S, &l, flag)) goto DONE; } DONE: (void)delete_var(); if (l == 1) return flag? NULL: dbasis(p, S->f, mf, S->phi, S->chi); return Decomp(S, flag); } 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.p = p; S.nu = h; S.df = Z_pval(D, p); if (l == 1) return nilord(&S, D, mf, 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); DT = absi(DT); fa = Z_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 norm_by_embed */ 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( norm_by_embed(S->r1, RgM_RgC_mul(S->M, a)), &e ); if (e > -5) pari_err(precer, "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->M = NULL; /* -Wall */ S->r1 = 0; /* -Wall */ S->D = NULL; /* -Wall */ S->w = NULL; /* -Wall */ S->T = NULL; /* -Wall */ if (typ(nf[5]) == t_VEC) /* beware dummy nf from padicff */ { GEN M = nf_get_M(nf); long ex = gexpo(M) + gexpo(mului(8 * N, p)); if (N * ex <= bit_accuracy(gprecision(M))) { /* enough prec to use norm_by_embed */ S->M = M; S->r1 = nf_get_r1(nf); } } 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(talker, "idealprimedec: %Ps is not prime", 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_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(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); } 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 = lg(mul[1]); 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) { GEN u, t; long e, f, N; if (typ(P) == t_VEC) return P; /* already done (Kummer) */ N = nf_get_degree(nf); f = N - (lg(P)-1); if (f == N) return mk_pr(p,scalarcol_shallow(p,N),1,f,gen_1); u = uniformizer(nf, S, P, V, p, ramif); /* P = (p,u) prime. t is an anti-uniformizer: Z_K + t/p Z_K = P^(-1) */ t = FpM_deplin(zk_multable(nf, u), p); e = ramif? 1 + int_elt_val(nf,t,p,t,NULL): 1; return mk_pr(p,u,e,f,t); } /* prime ideal decomposition of p */ static GEN primedec_aux(GEN nf, GEN p) { GEN E, F, L, Ip, H, phi, mat1, f, g, h, p1, UN, T = nf_get_pol(nf); long i, k, c, iL, N; F = FpX_factor(T, p); E = gel(F,2); F = gel(F,1); k = lg(F); if (k == 1) errprime(p); if ( !dvdii(nf_get_index(nf),p) ) /* p doesn't divide index */ { L = cgetg(k,t_VEC); 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); { GEN Lpr = cgetg(iL, 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; 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); } void checkmodpr(GEN modpr) { if (typ(modpr) != t_COL || lg(modpr) < SMALLMODPR) pari_err(talker,"incorrect modpr format"); checkprid(gel(modpr,mpr_PR)); } 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(modpr[mpr_T])); } /* REDUCTION Modulo a prime ideal */ /* x integral, reduce mod prh in HNF */ GEN nfreducemodpr_i(GEN x, GEN prh) { GEN p = gcoeff(prh,1,1); long i,j; x = leafcopy(x); for (i=lg(x)-1; i>=2; i--) { GEN t = gel(prh,i), p1 = remii(gel(x,i), p); gel(x,i) = p1; if (signe(p1) && is_pm1(gel(t,i))) { for (j=1; jmultab,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 rnfelementid_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 = leftright_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); F[1] = rnfId[1]; for (j=2; j<=n; j++) gel(F,j) = rnfelementid_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,"rnfordmax"); gerepileall(av1,2, &W,&I); } } return gerepilecopy(av, mkvec2(W, I)); } static void check_pol(GEN *px) { GEN x = *px; long i, lx = lg(x); for (i=2; i= 0) pari_err(talker,"incorrect polynomial in rnf function"); Q[1] = P[1]; for (i=2; i= lg(T)) c = RgX_rem(c,T); check_pol(&c); if (!lift && typ(c) == t_POL) c = mkpolmod(c, T); break; case t_POLMOD: if (!RgX_equal_var(gel(c,1), T)) pari_err(consister,"rnf function"); if (lift) c = gel(c,2); break; default: pari_err(typeer, "rnf function"); } gel(Q,i) = c; } return normalizepol_lg(Q, lP); } /* determinant of the trace pairing */ static GEN get_d(GEN nf, GEN pol, GEN A) { long i, j, n = degpol(pol); GEN W = RgM_to_RgXV(lift_intern(matbasistoalg(nf,A)), varn(pol)); GEN T, nfT = nf_get_pol(nf), sym = polsym_gen(pol, NULL, n-1, nfT, NULL); T = cgetg(n+1,t_MAT); for (j=1; j<=n; j++) gel(T,j) = cgetg(n+1,t_COL); for (j=1; j<=n; j++) for (i=j; i<=n; i++) { GEN c = RgXQX_mul(gel(W,i),gel(W,j), nfT); c = RgXQX_rem(c, pol, nfT); c = simplify_shallow(quicktrace(c,sym)); gcoeff(T,j,i) = gcoeff(T,i,j) = c; } return nf_to_scalar_or_basis(nf, det(T)); } /* nf = base field K * pol= monic polynomial, coefficients in Z_K, defining a relative * extension L = K[X]/(pol). One MUST have varn(pol) << nf_get_varn(nf). * Returns a pseudo-basis [A,I] of Z_L, set (D,d) to the relative * discriminant, and f to the index-ideal */ GEN rnfallbase(GEN nf, GEN *ppol, GEN *pD, GEN *pd, GEN *pf) { long i, n, l; GEN A, nfT, fa, E, P, I, z, d, D, disc, pol = *ppol; nf = checknf(nf); nfT = nf_get_pol(nf); pol = rnf_fix_pol(nfT,pol,0); if (!gequal1(leading_term(pol))) pari_err(impl,"non-monic relative polynomials"); n = degpol(pol); disc = RgX_disc(pol); pol = lift_intern(pol); fa = idealfactor(nf, disc); P = gel(fa,1); l = lg(P); E = gel(fa,2); z = NULL; for (i=1; i < l; i++) { long e = itos(gel(E,i)); if (e > 1) z = rnfjoinmodules(nf, z, rnfordmax(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 && ideal_is1(gel(I,i))) { gel(I,i) = gen_1; 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 (z == gen_0) { avma = av; return NULL; } return z; } /* 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 (typ(x) != t_VEC || lg(x) < 3) pari_err(talker,"not a pseudo-basis in nfsimplifybasis"); 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 (typ(O)!=t_VEC || lg(O) < 3 || typ(O[1]) != t_MAT || typ(O[2]) != t_VEC || lg(O[1]) != lg(O[2])) pari_err(talker,"not a pseudo-matrix in %s", s); 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 **/ /** **/ /**********************************************************************/ /* 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 || typ(B)!=t_POL) pari_err(typeer,"polcompositum0"); if (degpol(A)<=0 || degpol(B)<=0) pari_err(constpoler,"compositum"); v = varn(A); if (varn(B) != v) pari_err(talker,"not the same variable in compositum"); same = (A == B || RgX_equal(A,B)); A = Q_primpart(A); RgX_check_ZX(A,"compositum"); if (!ZX_is_squarefree(A)) pari_err(talker,"compositum: %Ps inseparable", A); if (!same) { B = Q_primpart(B); RgX_check_ZX(B,"compositum"); if (!ZX_is_squarefree(B)) pari_err(talker,"compositum: %Ps inseparable", 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 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 = lg(x[1]); 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; GEN z; if (lx == 1) return gen_0; av = avma; z = gsqr(gel(x,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 (typ(x) != t_MAT || l != lg(x[1])) pari_err(mattype1,"RgM_Rg_add"); z = cgetg(l,t_MAT); for (i=1; i1? lg(x[1]): 1 */ static GEN RgM_RgC_mul_i(GEN x, GEN y, long l, long lz) { GEN z = cgetg(lz,t_COL); long i, j; for (i=1; i 1 ! */ for (j=2; j>1)) : RgM_mul(gel(V, i-1), x); return V; } GEN RgC_Rg_div(GEN x, GEN y) { long i, lx = lg(x); GEN z = cgetg(lx, t_COL); for (i=1; i 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(talker,"incorrect variable in charpoly"); 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,NULL))) 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))); } /* 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; } /* 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, l; GEN p, y, t; if ((p = easychar(x, v, py))) return p; l = lg(x); av0 = avma; p = cgetg(l+2,t_POL); p[1] = evalsigne(1) | evalvarn(v); gel(p,l+1) = gen_1; if (l == 1) { if (py) *py = cgetg(1,t_MAT); return p; } av = avma; t = gerepileupto(av, gneg(mattrace(x))); gel(p,l) = t; if (l == 2) { p = fix_pol(av0, p); if (py) *py = matid(1); return p; } if (l == 3) { 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(p,2) = gerepileupto(av, gsub(gmul(a,d), gmul(b,c))); p = fix_pol(av0, p); 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 p; } /* l > 3 */ av = avma; y = RgM_shallowcopy(x); for (i = 1; i < l; i++) gcoeff(y,i,i) = gadd(gcoeff(y,i,i), t); for (k = 2; k < l-1; k++) { GEN y0 = y; y = RgM_mul(y, x); t = gdivgs(mattrace(y), -k); for (i = 1; i < l; i++) gcoeff(y,i,i) = gadd(gcoeff(y,i,i), t); y = gclone(y); gel(p,l-k+1) = gerepilecopy(av, t); av = avma; if (k > 2) gunclone(y0); } t = gmul(gcoeff(x,1,1),gcoeff(y,1,1)); for (i=2; i1) pari_warn(warnmem,"hess, m = %ld", m); gerepileall(av,2, &x, &t); } } } return gerepilecopy(av,x); } GEN Flm_hess(GEN x, ulong p) { pari_sp av = avma; long lx = lg(x), m, i, j; if (typ(x) != t_MAT) pari_err(mattype1,"hess"); if (lx == 1) return cgetg(1,t_MAT); if (lg(x[1]) != lx) pari_err(mattype1,"hess"); x = Flm_copy(x); for (m=2; m= (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; ulong p; byteptr d; 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); } d = init_modular(&p); for(;;) { NEXT_PRIME_VIADIFF_CHECK(p,d); 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 { GEN qp = muliu(q, p); int stable = ZX_incremental_CRT(&H, Hp, q,qp, p); if (DEBUGLEVEL>5) timer_printf(&T, "charpoly mod %lu (stable=%ld), bound = 2^%ld", p, stable, expi(qp)); if (stable && expi(qp) > bit) break; q = qp; } } 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,NULL))) 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; gel(V,2) = gcoeff(x,1,1); for (i=2;i<=lx; i++) gel(S,i) = gen_0; for (i=2;i<=lx; i++) gel(C,i) = gen_0; for (i=2;i<=lx; i++) gel(Q,i) = gen_0; 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: return RgXQ_norm(gel(x,2), gel(x,1)); case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i=1; i1) pari_warn(warnmem,"gnorml2"); s = gerepileupto(av, s); } } return gerepileupto(av,s); } 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 i, lx; GEN z; switch(typ(x)) { case t_COMPLEX: z = cxnorm(x); store(z, msq); return; case t_QUAD: z = quadnorm(x); 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(typeer,"gsupnorm"); return; /* not reached */ } for (i=1; i= 2*/ if (lx != lg(x[1])) pari_err(mattype1,"gtrace"); av = avma; return gerepileupto(av, mattrace(x)); } pari_err(typeer,"gtrace"); return NULL; /* not reached */ } /* Gauss decomposition for positive definite matrix a [matrix Q, Algo 2.7.6] * If a is not positive definite return NULL. */ GEN qfgaussred_positive(GEN a) { pari_sp av = avma, lim=stack_lim(av,1); GEN b; long i,j,k, n = lg(a); if (typ(a)!=t_MAT) pari_err(typeer,"qfgaussred_positive"); if (n == 1) return cgetg(1, t_MAT); if (lg(a[1])!=n) pari_err(mattype1,"qfgaussred_positive"); b = cgetg(n,t_MAT); for (j=1; j1) pari_warn(warnmem,"qfgaussred_positive"); b=gerepilecopy(av,b); } } return gerepilecopy(av,b); } /* 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, p, invp, 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(typeer,"gaussred"); if (n == 1) return signature? mkvec2(gen_0, gen_0): cgetg(1, t_MAT); if (lg(a[1]) != n) pari_err(mattype1,"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) { k=1; while (k<=n && (!r[k] || gequal0(gcoeff(a,k,k)))) k++; 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] || gequal0(gcoeff(a,k,l)))) l++; 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(mattype1,"jacobi"); 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 (lg(a[1]) != l) pari_err(mattype1,"jacobi"); e1 = HIGHEXPOBIT-1; for (j=1; j e2) { e2 = e; p = i; q = j; } } } a = c; unr = real_1(prec); de = bit_accuracy(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(typeer,"QM_minors_coprime"); if (!p) return QM_minors_coprime(x,NULL); if (typ(p) != t_INT) pari_err(typeer,"QM_minors_coprime"); 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(flagerr,"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 = lg(x[1])-1; if (n > m) pari_err(talker,"need more rows than columns in QM_minors_coprime"); if (n==m) { D = det(x); if (gequal0(D)) pari_err(talker,"matrix of non-maximal rank in QM_minors_coprime"); avma = av; return matid(n); } /* m > n */ 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 (!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, prime 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 = lg(A[1]); 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 = lg(x[1]); x = RgM_shallowcopy(x); c = const_vecsmall(n-1, 0); 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 || typ(y)!=t_MAT) pari_err(typeer,"intersect"); 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.5.5/src/basemath/base4.c0000644000175000017500000022666212147140046014636 0ustar billbill/* $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. */ /*******************************************************************/ /* */ /* 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 != lg(x[1])) pari_err(talker,"non-square t_MAT in idealtyp"); t = id_MAT; break; case t_VEC: if (lg(x)!=6) pari_err(talker, "incorrect ideal in idealtyp"); 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(talker, "incorrect ideal in idealtyp"); 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(typeer,"idealhnf"); } 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) { GEN cx; long tx = typ(x), lx = lg(x); /* 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 */ if (tx == t_MAT) { long nx = lx-1, N = nf_get_degree(nf); if (nx == 0) return cgetg(1, t_MAT); if (lg(x[1])-1 != N) pari_err(talker,"incorrect dimension in idealhnf"); 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; } 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(flagerr,"idealdiv"); } return NULL; /* not reached */ } GEN idealaddtoone0(GEN nf, GEN arg1, GEN arg2) { if (!arg2) return idealaddmultoone(nf,arg1); return idealaddtoone(nf,arg1,arg2); } 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 = zk_scalar_or_multable(nf, b); if (typ(b) == t_INT) { b = gcdii(b,a); return db? mkfraccopy(b, db): a; } else { b = hnfmodid(b, a); return db? RgM_Rg_div(b, db): b; } } static GEN hnf_Q_QC(GEN nf, GEN a, GEN b) { GEN db, da; 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); b = ZC_Z_mul(b, da); if (db) { GEN d = gcdii(da,db); db = diviiexact(db,d); a = mulii(a, db); da = mulii(da, db); /* lcm(denom(a),denom(b)) */ } b = zk_scalar_or_multable(nf, b); if (typ(b) == t_INT) return gdiv(gcdii(b, a), da); return RgM_Rg_div(hnfmodid(b, a), 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(ggcd(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 v_P <= e * v_p */ j = k * e; /* 0 <= v_P(ix) <= floor[v_p(Nix) / f] */ i = i / f; vmax = minss(i,j); /* v_P(ix) <= vmax */ t0 = pr_get_tau(P); if (typ(t0) == t_MAT) { /* t0 given by a multiplication table */ mul = t0; do_mul = 0; } else /* always a t_COL since f < N, never a t_INT */ { mul = cgetg(N+1,t_MAT); gel(mul,1) = t0; do_mul = 1; } B = cgetg(N+1,t_MAT); pk = powiu(p, (ulong)ceil((double)vmax / e)); /* B[1] not needed: v_pr(ix[1]) = v_pr(ix \cap Z) is known already */ gel(B,1) = gen_0; /* dummy */ for (j=2; j<=N; j++) { if (do_mul) gel(mul,j) = zk_ei_mul(nf,t0,j); x = gel(ix,j); y = cgetg(N+1, t_COL); gel(B,j) = y; for (i=1; i<=N; i++) { /* compute a = (x.t0)_i, ix in HNF ==> x[j+1..N] = 0 */ a = mulii(gel(x,1), gcoeff(mul,i,1)); for (k=2; k<=j; k++) a = addii(a, mulii(gel(x,k), gcoeff(mul,i,k))); /* p | a ? */ gel(y,i) = dvmdii(a,p,&r); if (signe(r)) { avma = av; return vd; } } } vals = cgetg(N+1, t_VECSMALL); /* vals[1] not needed */ for (j = 2; j <= N; j++) { gel(B,j) = Q_primitive_part(gel(B,j), &cx); vals[j] = cx? 1 + e * Q_pval(cx, p): 1; } av1 = avma; lim = stack_lim(av1,3); y = cgetg(N+1,t_COL); /* can compute mod p^ceil((vmax-v)/e) */ for (v = 1; v < vmax; v++) { /* we know v_pr(Bj) >= v for all j */ if (e == 1 || (vmax - v) % e == 0) pk = diviiexact(pk, p); for (j = 2; j <= N; j++) { x = gel(B,j); if (v < vals[j]) continue; for (i=1; i<=N; i++) { pari_sp av2 = avma; a = mulii(gel(x,1), gcoeff(mul,i,1)); for (k=2; k<=N; k++) a = addii(a, mulii(gel(x,k), gcoeff(mul,i,k))); /* a = (x.t_0)_i; p | a ? */ a = dvmdii(a,p,&r); if (signe(r)) { avma = av; return v + vd; } if (lgefint(a) > lgefint(pk)) a = remii(a, pk); gel(y,i) = gerepileuptoint(av2, a); } gel(B,j) = y; y = x; if (low_stack(lim,stack_lim(av1,3))) { if(DEBUGMEM>1) pari_warn(warnmem,"idealval"); gerepileall(av1,3, &y,&B,&pk); } } } avma = av; return v + vd; } /* gcd and generalized Bezout */ GEN idealadd(GEN nf, GEN x, GEN y) { pari_sp av = avma; long tx, ty; GEN z, a, dx, dy, dz; tx = idealtyp(&x,&z); ty = idealtyp(&y,&z); nf = checknf(nf); if (tx != id_MAT) x = idealhnf_shallow(nf,x); if (ty != id_MAT) y = idealhnf_shallow(nf,y); if (lg(x) == 1) return gerepilecopy(av,y); if (lg(y) == 1) return gerepilecopy(av,x); /* check for 0 ideal */ dx = Q_denom(x); dy = Q_denom(y); dz = lcmii(dx,dy); if (is_pm1(dz)) dz = NULL; else { x = Q_muli_to_int(x, dz); y = Q_muli_to_int(y, dz); } a = gcdii(gcoeff(x,1,1), gcoeff(y,1,1)); if (is_pm1(a)) { long N = lg(x)-1; if (!dz) { avma = av; return matid(N); } return gerepileupto(av, scalarmat(ginv(dz), N)); } z = ZM_hnfmodid(shallowconcat(x,y), a); if (dz) z = RgM_Rg_div(z,dz); return gerepileupto(av,z); } static GEN trivial_merge(GEN x) { long lx = lg(x); GEN a; if (lx == 1) return NULL; a = gcoeff(x,1,1); if (!is_pm1(a)) return NULL; return scalarcol_shallow(gen_1, lx-1); } GEN idealaddtoone_i(GEN nf, GEN x, GEN y) { GEN a; long tx = idealtyp(&x, &a/*junk*/); long ty = idealtyp(&y, &a/*junk*/); if (tx != id_MAT) x = idealhnf_shallow(nf, x); if (ty != id_MAT) y = idealhnf_shallow(nf, y); if (lg(x) == 1) a = trivial_merge(y); else if (lg(y) == 1) a = trivial_merge(x); else { a = hnfmerge_get_1(x, y); if (a) a = ZC_reducemodlll(a, idealmul_HNF(nf,x,y)); } if (!a) pari_err(talker, "non coprime ideals in idealaddtoone"); return a; } GEN unnf_minus_x(GEN x) { long i, N = lg(x); GEN y = cgetg(N,t_COL); gel(y,1) = gsubsg(1, gel(x,1)); for (i=2; i1; i--) t = nfmul(nf, t, nfpow(nf, gel(x,i), gel(e,i))); return t; } /* "compare" two nf elt. Goal is to quickly sort for uniqueness of * representation, not uniqueness of represented element ! */ static int elt_cmp(GEN x, GEN y) { long tx = typ(x), ty = typ(y); if (ty == tx) return (tx == t_POL || tx == t_POLMOD)? cmp_RgX(x,y): lexcmp(x,y); return tx - ty; } static int elt_egal(GEN x, GEN y) { if (typ(x) == typ(y)) return gequal(x,y); return 0; } GEN famat_reduce(GEN fa) { GEN E, G, L, g, e; long i, k, l; if (lg(fa) == 1) return fa; g = gel(fa,1); l = lg(g); e = gel(fa,2); L = gen_indexsort(g, (void*)&elt_cmp, &cmp_nodata); G = cgetg(l, t_COL); E = cgetg(l, t_COL); /* merge */ for (k=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 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); GEN mul = zk_scalar_or_multable(nf, pr_get_tau(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)int_elt_val(nf, x, p, mul, &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 { 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(typeer, "idealnorm"); 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 dual, IZ = gcoeff(I,1,1); /* I \cap Z */ GEN 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(consister,"idealinv"); x = idealinv_HNF(nf,x); break; case id_PRINCIPAL: tx = typ(x); if (is_const_t(tx)) x = ginv(x); else { 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; } if (varn(x) != nf_get_varn(nf)) pari_err(talker,"incompatible variables in idealinv"); x = QXQ_inv(x,nf_get_pol(nf)); } 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; } /* 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); *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) { n = negi(n); gen = ZC_Z_divexact(nfpow(nf, pr_get_tau(pr), 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(talker,"non-integral exponent in idealpow"); 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(talker,"non-integral exponent in idealpowred"); 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 (lx==6); case t_MAT: break; default: return 0; } N = degpol(T); if (lx-1 != N) return (lx == 1); if (lg(x[1])-1 != N) return 0; av = avma; x = Q_primpart(x); if (!ZM_ishnf(x)) return 0; for (i=1; 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(talker, "cannot invert zero ideal"); 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(talker, "quotient not integral in idealdivexact"); /* 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(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(talker,"not a prime ideal factorization in idealchinese"); L = gel(x,1); r = lg(L); e = gel(x,2); if (!is_vec_t(ty) || lg(w) != r) pari_err(talker,"not a suitable vector of elements in idealchinese"); if (r == 1) return scalarcol_shallow(gen_1,N); w = Q_remove_denom(w, &den); if (den) { GEN p = gen_indexsort(x, (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; i=1; i--) { GEN d, di = NULL; def--; j=def; while (j>=1 && gequal0(gcoeff(A,i,j))) j--; if (!j) pari_err(talker,"not a matrix of maximal rank in nfhnf"); if (j==def) j--; else { swap(gel(A,j), gel(A,def)); swap(gel(I,j), gel(I,def)); } y = gcoeff(A,i,def); gel(A,def) = nfC_nf_mul(nf, gel(A,def), nfinv(nf,y)); gel(I,def) = idealmul(nf, y, gel(I,def)); for ( ; j; j--) { GEN b, u,v,w, S, T, S0, T0 = gel(A,j); b = gel(T0,i); if (gequal0(b)) continue; S0 = gel(A,def); d = nfbezout(nf, gen_1,b, gel(I,def),gel(I,j), &u,&v,&w,&di); S = colcomb(nf, u,v, S0,T0); gel(S,i) = gen_1; T = colcomb1(nf,gneg(b), T0,S0); gel(T,i) = gen_0; gel(A,def) = S; gel(A,j) = T; gel(I,def) = d; gel(I,j) = w; } d = gel(I,def); if (!di) di = idealinv(nf,d); gel(J,def) = di; for (j=def+1; j<=k; j++) { GEN c = element_close(nf,gcoeff(A,i,j), idealmul(nf,d,gel(J,j))); gel(A,j) = colcomb1(nf, gneg(c), gel(A,j),gel(A,def)); } if (low_stack(lim, stack_lim(av1,2))) { if(DEBUGMEM>1) pari_warn(warnmem,"nfhnf, i = %ld", i); gerepileall(av,3, &A,&I,&J); } } A += k-m; A[0] = evaltyp(t_MAT)|evallg(m+1); I += k-m; I[0] = evaltyp(t_VEC)|evallg(m+1); 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(talker,"not a module in nfsnf"); A = gel(x,1); I = gel(x,2); J = gel(x,3); if (typ(A)!=t_MAT) pari_err(talker,"not a matrix in nfsnf"); n = lg(A)-1; if (typ(I)!=t_VEC || lg(I)!=n+1 || typ(J)!=t_VEC || lg(J)!=n+1) pari_err(talker,"not a correct ideal list in nfsnf"); if (!n) pari_err(talker,"not a matrix of maximal rank in nfsnf"); m = lg(A[1])-1; if (n < m) pari_err(talker,"not a matrix of maximal rank in nfsnf"); if (n > m) pari_err(impl,"nfsnf for 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(talker,"bug2 in 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); z = Fq_mul(nf_to_Fq(nf,x,modpr), nf_to_Fq(nf,y,modpr),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(typeer,"nfkermodpr"); 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) { pari_sp av = avma; GEN T, p, modpr; long tb = typ(b); nf = checknf(nf); modpr = nf_to_Fq_init(nf, &pr,&T,&p); if (typ(a)!=t_MAT) pari_err(typeer,"nfsolvemodpr"); a = nfM_to_FqM(a, nf, modpr); switch(tb) { case t_MAT: b = nfM_to_FqM(b, nf, modpr); a = FqM_to_nfM(FqM_gauss(a,b,T,p), modpr); break; case t_COL: b = nfV_to_FqV(b, nf, modpr); a = FqV_to_nfV(FqM_gauss(a,b,T,p), modpr); break; default: pari_err(typeer,"nfsolvemodpr"); } 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 = lg(A[1]); 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 (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 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 = lg(A[1]); detmat = Q_remove_denom(detmat, NULL); if (typ(detmat)!=t_MAT) pari_err(typeer,"nfhnfmod"); RgM_check_ZM(detmat, "nfhnfmod"); av = avma; lim = stack_lim(av,2); A = RgM_to_nfM(nf, A); I = leafcopy(I); def = co; ldef = (li>co)? li-co+1: 1; for (i=li-1; i>=ldef; i--) { def--; j=def; while (j>=1 && gequal0(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 (gequal0(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,2, &A,&I); } } def--; d0 = detmat; A += def; A[0] = evaltyp(t_MAT)|evallg(li); I += def; I[0] = evaltyp(t_VEC)|evallg(li); for (i=li-1; i>=1; i--) { d = nfbezout(nf, gen_1,gcoeff(A,i,i), d0,gel(I,i), &u,&v,&w,&di); p1 = RgC_to_nfC(nf, 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; } J = cgetg(li,t_VEC); gel(J,1) = gen_0; for (j=2; j=1; i--) { d = gel(I,i); for (j=i+1; j1) pari_warn(warnmem,"[2]: nfhnfmod, i = %ld", i); gerepileall(av,3, &A,&I,&J); } } return gerepilecopy(av0, mkvec2(A, I)); } pari-2.5.5/src/basemath/ifactor1.c0000644000175000017500000042127612147140046015346 0ustar billbill/* $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. */ #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(arither1); 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); } 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(arither1); if (signe(n) <= 0) { avma = av; return gen_0; } if (lgefint(n) <= 3) { /* check if n <= 10 */ ulong k = n[2]; if (k <= 1) { avma = av; return gen_0; } if (k == 2) { avma = av; return gen_2; } if (k <= 4) { avma = av; return utoipos(3); } if (k <= 6) { avma = av; return utoipos(5); } if (k <= 10) { avma = av; return utoipos(7); } } /* here n >= 11 */ 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); } GEN gnextprime(GEN n) { return map_proto_G(nextprime,n); } GEN gprecprime(GEN n) { return map_proto_G(precprime,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; this makes sense * 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); if (*rcn != NPRC) { long rcn0 = *rcn; while (d1 > 0) { d1 -= prc210_d1[*rcn]; if (++*rcn > 47) { *rcn = 0; if (q) (*q)++; } } if (d1 < 0) { err_printf("snextpr: %lu != prc210_rp[%ld] mod 210\n", p, rcn0); pari_err(bugparier, "[caller of] snextpr"); } } 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) { err_printf("snextpr: %lu should have been prime but isn\'t\n", p); pari_err(bugparier, "[caller of] snextpr"); } } /* 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 (++*rcn > 47) { *rcn = 0; if (q) (*q)++; } if (n <= 11) /* wraparound mod 2^BITS_IN_LONG */ { err_printf("snextpr: integer wraparound after prime %lu\n", p); pari_err(bugparier, "[caller of] snextpr"); } } 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 nontrivial factor of N but finite mod some * other factor (betraying itself by a denominator which has nontrivial gcd * with N, and this is of course what we want). */ /* (In the second case, addition/doubling will simply abort, 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.) */ /* The idea is: Select a handful of curves mod N and one point P on each of * them. Try to compute, for each such point, the multiple [M]P = Q where * M is the product of all powers <= B2 of primes <= nextprime(B1), for some * suitable B1 and B2. Then check whether multiplying Q by one of the * primes < nextprime(B2) would betray a factor. This second stage proceeds * by looking separately at the primes in each residue class mod 210, four * curves at a time, and stepping 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 trick (hiding the cost of computing inverses mod N at a * price of three extra multiplications mod N, by working on up to 64 or * even 128 points in parallel) is used heavily. */ /* *** auxiliary functions for ellfacteur: *** */ /* Parallel addition on nbc curves, assigning the result to locations at and * following *X3, *Y3. Safe to be called with X3,Y3 equal to X2,Y2 (_not_ * to X1,Y1). It is also safe to overwrite Y2 with X3. (If Y coords of * result not desired, set Y3=NULL.) If nbc1 < nbc, the first summand is * assumed to hold only nbc1 distinct points, which are repeated as often * as we need them (useful for adding one point on each of a few curves * to several other points on the same curves). * Return 0 when successful, 1 when we hit a denominator divisible by N, * and 2 when gcd(denominator, N) is a nontrivial factor of N, which will * be 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 * four are twice as long and one is thrice as long as N -- makes 18 units * per iteration. Phase 1 creates 4 units. Total can be as large as * about 4*nbcmax + 18*8 units. And elladd2() is just as bad, and * elldouble() comes to about 3*nbcmax + 29*8 units. A few strategic garbage * collections every 8 iterations may help when nbc is large.) */ static int elladd0(GEN N, GEN *gl, long nbc, long nbc1, GEN *X1, GEN *Y1, GEN *X2, GEN *Y2, GEN *X3, GEN *Y3) { GEN W[2*nbcmax], *A = W+nbc; /* W[0],A[0] unused */ long i; pari_sp av = avma, tetpil; ulong mask = ~0UL; /* actually, this is only ever called with nbc1==nbc or nbc1==4, so: */ if (nbc1 == 4) mask = 3; else if (nbc1 < nbc) pari_err(bugparier, "[caller of] elladd0"); W[1] = subii(X1[0], X2[0]); for (i=1; i2 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; long i; int res; GEN *A = X2, *B = XAUX, *S, *T = XAUX + 2*nbc; for (i = 2*nbc; i--; ) affii(X1[i], XAUX[i]); /* 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. First * figure out which, and then go into an eight-way switch, because * some of the transformations are similar enough to share code. */ if (d <= e + (e>>2)) /* floor(1.25*e) */ { if ((d+e)%3 == 0) { i = 0; goto apply; } /* rule 1 */ if ((d-e)%6 == 0) { i = 1; goto apply; } /* rule 2 */ } /* else fall through */ /* d <= 4*e but no ofl */ if ((d+3)>>2 <= e){ i = 2; goto apply; } /* rule 3, common case */ if ((d&1)==(e&1)) { i = 1; goto apply; } /* rule 4 = rule 2 */ if (!(d&1)) { i = 3; goto apply; } /* rule 5 */ if (d%3 == 0) { i = 4; goto apply; } /* rule 6 */ if ((d+e)%3 == 0) { i = 5; goto apply; } /* rule 7 */ if ((d-e)%3 == 0) { i = 6; goto apply; } /* rule 8 */ /* when we get here, e must be even, for otherwise one of rules 4,5 * would have applied */ i = 7; /* rule 9 */ apply: switch(i) /* i takes values in {0,...,7} here */ { case 0: /* rule 1 */ e1 = d - e; d = (d + e1)/3; e = (e - e1)/3; if ( (res = elladd(N, gl, nbc, A, B, T)) ) return res; if ( (res = elladd2(N, gl, nbc, T, A, A, T, B, B)) != 0) return res; break; /* end of rule 1 */ case 1: /* rules 2 and 4, part 1 */ d -= e; if ( (res = elladd(N, gl, nbc, A, B, B)) ) return res; /* FALL THROUGH */ case 3: /* rule 5, and 2nd part of rules 2 and 4 */ d >>= 1; if ( (res = elldouble(N, gl, nbc, A, A)) ) return res; break; /* end of rules 2, 4, and 5 */ case 4: /* rule 6 */ d /= 3; if ( (res = elldouble(N, gl, nbc, A, T)) ) return res; if ( (res = elladd(N, gl, nbc, T, A, A)) ) return res; /* FALL THROUGH */ case 2: /* rule 3, and 2nd part of rule 6 */ d -= e; if ( (res = elladd(N, gl, nbc, A, B, B)) ) return res; break; /* end of rules 3 and 6 */ case 5: /* rule 7 */ d = (d - e - e)/3; if ( (res = elldouble(N, gl, nbc, A, T)) ) return res; if ( (res = elladd2(N, gl, nbc, T, A, A, T, B, B)) != 0) return res; break; /* end of rule 7 */ case 6: /* rule 8 */ d = (d - e)/3; if ( (res = elladd(N, gl, nbc, A, B, B)) ) return res; if ( (res = elldouble(N, gl, nbc, A, T)) ) return res; if ( (res = elladd(N, gl, nbc, T, A, A)) ) return res; break; /* end of rule 8 */ case 7: /* rule 9 */ e >>= 1; if ( (res = elldouble(N, gl, nbc, B, B)) ) return res; break; /* end of rule 9 */ default: break; /* notreached */ } /* end of Table 4 processing */ /* swap d <-> e and A <-> B if necessary */ if (d < e) { r = d; d = e; e = r; S = A; A = B; B = S; } } /* while */ return 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 elladd() which does not depend on the third argument; and * thus all references to the third variable (C in the paper) can be elimi- * nated. (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 it will * always be followed by a swap, so we have unrolled this first iteration. * (4) Some simplifications in rules 6 and 7 are possible given the above, * and we can save one addition in each of the two cases. NB one can show * that none of the other elladd()s in the loop can ever turn out to de- * generate into an elldouble. (5) I tried to optimize for rule 3, which * is used far 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 slightly _slower_ under PRAC than * under a straightforward left-shift binary multiplication algorithm when * N has <30 digits and B1 is small; PRAC wins when N and B1 get larger. * Weird. --GN */ /* memory layout in ellfacteur(): We'll have a large-ish 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. Now 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, and another 4096 slots for * the baby step table (not all of which will be used when we start with a * small B1, but it's 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 E.C. 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, much faster */ /* 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 (see http://www.loria.fr/~zimmerma/ and especially * http://www.loria.fr/~zimmerma/records/ecmnet.html). --GN 1998Jul,Aug */ GEN ellfacteur(GEN N, int insist) { const ulong TB1[] = { /* table revised, cf. below 1998Aug15 --GN */ 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, /* the only reason to stop here is that I got bored (and that users will * get bored watching their 64bit machines churning on such large numbers * for month after month). Someone can extend this table when the hardware * has gotten 100 times faster than now --GN */ #endif }; const ulong TB1_for_stage[] = { /* table revised 1998Aug11 --GN. * Start a little below the optimal B1 for finding factors which would just * have been missed by pollardbrent(), and escalate gradually, changing * curves sufficiently frequently to give good coverage of the small factor * ranges. Entries grow a bit faster than what Paul says 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 we'll start, how long we'll persist, and how many * curves we'll use in parallel */ if (insist) { dsnmax = (size >> 2) - 10; if (dsnmax < 0) dsnmax = 0; #ifdef LONG_IS_64BIT else if (dsnmax > 90) dsnmax = 90; #else else if (dsnmax > 65) dsnmax = 65; #endif 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__ /* MPQS's disk access under DOS/EMX would be abysmally slow, so... */ 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 } /* it may be convenient to use disjoint sets of curves for the 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; it would be complicated to * skip them here to conserve merely a few KBy of stack or heap space. */ /* ECM MAIN LOOP */ 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, appro- * priate for the smallest B2s. With 1024, a giant step will be 430080; * this will be 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; /* p^2 > B2: no loop */ 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, which we need 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 (elladd(N, &gl, nbc, XD, XD + nbc2, XD + (nbc<<2)) > 1) goto fin; /* [6]Q */ if (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(bugparier, "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; but * 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 (elladd(N, &gl, nbc, XT + dp*nbc, XH + rcn*nbc2, XH) > 1) goto fin; rcn = 0; continue; } if (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, which will be 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 (elladd(N, &gl, nbc, X, XAUX, XT) > 1) goto fin;/* [630]Q */ if (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. Recall memory layout in XH is * nbc X coordinates followed by 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 will allow us to do a giant step on Xh using just three * calls to 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 (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 (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 (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 (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 will be incre- * mented 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 may * 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. */ /* loop over probable primes p0 < p <= nextprime(B2), inserting giant * steps as necessary */ while (p < B2) { ulong p2 = p; /* save current p for diagnostics */ /* 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)) { p = p2; goto fin; } gl = gen_1; avma = av1; while (k > gss) /* hm, just how large are those prime gaps? */ { /* giant step */ if (DEBUGLEVEL >= 7) err_printf("\t(giant step at p = %lu)\n", p); if (elladd0(N, &gl, 64, 4, XG + i, YG + i, Xh, Yh, Xh, Yh) > 1) goto fin; if (elladd0(N, &gl, 64, 4, XG + i, YG + i, Xh + 64, Yh + 64, Xh + 64, Yh + 64) > 1) goto fin; if (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; } } /* END OF ECM MAIN LOOP */ 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; } INLINE void INIT0(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(bugparier,"squfof [caller of] (n or 3n is a square)"); c2 = itos(shifti(subii(D2, sqru((ulong)b2)), -2)); if (!c2) pari_err(bugparier,"squfof [caller of] (5n is a square)"); L1 = (long)usqrtsafe(d1); L2 = (long)usqrtsafe(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 */ }; /* 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), resbyte; ulong residue; pari_sp av; GEN y; *mask &= 7; /* paranoia */ if (!*mask) return 0; /* useful when running in a loop */ if (DEBUGLEVEL >= 5) { err_printf("OddPwrs: is %Ps\n\t...a", x); if (*mask&1) err_printf(" 3rd%s", (*mask==7?",":(*mask!=1?" or":""))); if (*mask&2) err_printf(" 5th%s", (*mask==7?", or":(*mask&4?" or":""))); if (*mask&4) err_printf(" 7th"); err_printf(" power?\n\tmodulo: resid. (remaining possibilities)\n"); } residue = (lx == 3)? (ulong)x[2]: umodiu(x, 211*209*61*203); #define check_res(N, shift) {\ resbyte = residue%N; if ((ulong)resbyte > (N>>1)) resbyte = N - resbyte;\ *mask &= (powersmod[resbyte] >> shift); \ if (DEBUGLEVEL >= 5)\ err_printf("\t %3ld: %3ld (3rd %ld, 5th %ld, 7th %ld)\n",\ N, resbyte, *mask&1, (*mask>>1)&1, (*mask>>2)&1);\ if (!*mask) return 0;\ } check_res(211, 0); if (*mask & 3) check_res(209UL, 3); if (*mask & 3) check_res( 61UL, 6); if (*mask & 5) check_res(203UL, 9); residue = (lx == 3)? (ulong)x[2]: umodiu(x, 117*31*43*71); if (*mask & 1) check_res(117UL,12); if (*mask & 3) check_res( 31UL,15); if (*mask & 5) check_res( 43UL,18); if (*mask & 6) check_res( 71UL,21); 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, DEFAULTPREC + (lx-2) / 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 >= 5) 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, byteptr d) { int init = 0; long j; ulong q, residue; GEN y; byteptr d0; pari_sp av = avma; if (d) { q = n; d0 = d; } else { q = 0; d0 = diffptr; maxprime_check(n); while (q < n) NEXT_PRIME_VIADIFF(q,d0); } /* 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 want this < 1e-6 ~ exp(-13.8). * n = 17886697 is smallest such that the smallest suitable q is > 2^32 */ j = (long)(13.8 / log((double)n)); if (j < 1 && n < 17886697) j = 1; for (; j > 0; j--) { do { if (*d0) NEXT_PRIME_VIADIFF(q,d0); else { if (init) q += n; else { init = 1; q += n+1 - q%n; } while (!uisprime(q)) q += n; break; } } while (q % n != 1); /* q a prime = 1 mod n */ if (DEBUGLEVEL>4) err_printf("\tchecking modulo %ld\n", q); residue = umodiu(x, q); if (residue == 0) { if (Z_lvalrem(x, q, &y) % n) { avma = av; return 0; } continue; } /* n-th power mod q ? */ if (Fl_powu(residue, (q-1)/n, q) != 1) { if (DEBUGLEVEL>4) err_printf("\t- ruled out\n"); avma = av; return 0; } } avma = av; if (DEBUGLEVEL>4) err_printf("OddPwrs: passed modular checks\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; } /* generic version for exponents 11 or larger. Cut off when x^(1/k) fits * into 'cutoffbits', since we would have found it by trial division. * Interface is similar to is_357_power(), but instead of the mask, we keep * the current test exponent around. 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. */ int is_pth_power(GEN x, GEN *pt, ulong *curexp, ulong cutoffbits) { long size = expi(x) /* not +1 */; ulong p = 11; pari_sp av = avma; byteptr d = diffptr+5; /* cutting off at 1 is safe, but direct root extraction attempts are * faster when trial division has been used to discover very small * bases. We become competitive at about cutoffbits = 4 */ if (!cutoffbits) cutoffbits = 1; /* prepare for iterating curexp over primes */ if (*curexp < 11) *curexp = 11; while (p < *curexp) { if (!*d) { p = unextprime(*curexp); break; } NEXT_PRIME_VIADIFF(p,d); } *curexp = p; if (DEBUGLEVEL>4) err_printf("OddPwrs: examining %Ps\n", x); /* check size of x vs. curexp */ while (size/p >= cutoffbits) { if (DEBUGLEVEL>4) err_printf("OddPwrs: testing for exponent %ld\n", p); /* if found, caller should call us again without changing *curexp */ if (is_kth_power(x, p, pt, d)) return p; NEXT_PRIME_VIADIFF(p,d); *curexp = 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,moebus) same using default hint. * * ifac_primary_factor() returns a prime divisor (not necessarily the * smallest) and the corresponding exponent. * * Encapsulated user interface: * - ifac_decomp() [ to be called by Z_factor_limit() ]: puts a succession of * prime divisor / exponent pairs onto the stack, unsorted. * * - For each of the arithmetic functions, there is 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, omega, bigomega, numdiv, sumdiv, sumdivk. * * 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 at any given * time 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 be 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 (although this will _very_ rarely * happen for random input!). 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, although * this will not often be the case. * * 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; convert to U_1^2 if they * happen to be equal (which they shouldn't -- squares are caught in stage 3.1). * Note that 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 little 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 and forward declarations: ***/ /* 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. */ static GEN ifac_find(GEN partial, GEN where); /* Return GEN pointing at the first nonempty slot strictly behind the current * *where, or NULL if such doesn't exist. Can be used to skip a range of * vacant slots, or to initialize *where in the first place (pass partial in * both args). */ static void ifac_realloc(GEN *partial, GEN *where, long new_lg); /* 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. */ static long ifac_crack(GEN *partial, GEN *where); /* Split the first (composite) entry. There _must_ already be room for another * factor below *where, and *where is updated. Factor and cofactor are inserted * in the correct order, updating *where, or factor^k is inserted if such should * be the case (leaving *where unchanged). The factor or factors are set to * unknown, and inherit the exponent (or a multiple thereof) of its/their * ancestor. Returns number of factors written into the structure (normally 2, * but 1 if a factor equalled its cofactor, and may be more than 1 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. */ static long ifac_insert_multiplet(GEN *partial, GEN *where, GEN facvec); /* 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 */ static long ifac_divide(GEN *partial, GEN *where); /* 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. */ static long ifac_sort_one(GEN *partial, GEN *where, GEN washere); /* 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(). * Return 1 if we see an exponent > 1 (in Moebius mode without completing the * update), 0 otherwise. */ static long ifac_resort(GEN *partial, GEN *where); /* 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. May update *where. Returns 1 when an ifac_sort_one() call * does so to indicate a repeated factor, or 0 if all such calls returned 0 */ static void ifac_defrag(GEN *partial, GEN *where); /* defragment: collect and squeeze out any unoccupied slots above *where * during a downward sweep. 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. *where is updated */ static void ifac_whoiswho(GEN *partial, GEN *where, long after_crack); /* 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 is nonnegative, only look at the * first after_crack things in the list (do nothing when it's zero) */ static GEN ifac_main(GEN *partial); /* main loop: iterate until smallest entry is a finished prime; returns * a 'where' pointer, or gen_1 if nothing left, or gen_0 in Moebius mode if * we aren't squarefree */ /* 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. */ #define LAST(x) x+lg(x)-3 #define FIRST(x) x+3 #define MOEBIUS(x) gel(x,1) #define HINT(x) gel(x,2) #define moebius_mode (MOEBIUS(*partial)) /* 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(talker, "'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(bugparier, "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) INIT0(here); return part; } static GEN ifac_start(GEN n, int moebius) { return ifac_start_hint(n,moebius,decomp_default_hint); } static GEN ifac_find(GEN partial, GEN where) { GEN scan, end = partial + lg(partial); #ifdef IFAC_DEBUG ifac_check(partial, where); #endif for (scan = where+3; scan < end; scan += 3) if (VALUE(scan)) return scan; return NULL; } /* simple defragmenter */ 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) INIT0(scan_new); /* erase junk */ } /* and complex version 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 NULL for the where argument; 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) INIT0(scan_new); *partial = newpart; } /* Bubble-sort-of-thing sort. Won't be exercised frequently, so this is ok */ static long ifac_sort_one(GEN *partial, GEN *where, GEN washere) { GEN old, scan = washere - 3; GEN value, exponent, class0, class1; long cmp_res; #ifdef IFAC_DEBUG ifac_check(*partial, *where); if (!washere || washere < *where || washere > LAST(*partial)) pari_err(talker, "'washere' out of bounds in ifac_sort_one"); #endif value = VALUE(washere); exponent = EXPON(washere); if (exponent != gen_1 && moebius_mode && cmpui(1,exponent) < 0) return 1; /* should have been detected by caller */ class0 = CLASS(washere); if (scan < *where) return 0; /* nothing to do, washere==*where */ 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(talker, "misaligned partial detected in ifac_sort_one"); INIT(scan, value, exponent, class0); return 0; } /* case cmp_res == 0: repeated factor detected */ if (DEBUGLEVEL >= 4) err_printf("IFAC: repeated factor %Ps\n\tin ifac_sort_one\n", value); if (moebius_mode) return 1; /* not squarefree */ 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(talker, "composite equals prime in ifac_sort_one"); else if (class0 != gen_0 && class1 == gen_0) pari_err(talker, "prime equals composite in ifac_sort_one"); else if (class0 == gen_2) /* should happen even less */ CLASS(scan) = class0; /* use it */ } else /* shouldn't happen either */ CLASS(scan) = class0; /* use it */ } /* 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; INIT0(old); /* finally, see whether *where should be pulled in */ if (old == *where) *where += 3; return 0; } /* the following loop around the former doesn't need to check moebius_mode * because ifac_sort_one() never returns 1 in normal mode */ static long ifac_resort(GEN *partial, GEN *where) { GEN scan, scan_end = LAST(*partial); long res; for (scan = *where; scan <= scan_end; scan += 3) if (VALUE(scan) && !CLASS(scan) /* slot occupied with an unknown */ && (res = ifac_sort_one(partial, where, scan)) ) return res; return 0; } static int ifac_isprime(GEN x) { int res = 0; if (!BPSW_psp_nosmalldiv(VALUE(x))) CLASS(x) = gen_0; /* composite */ else if (factor_proven && ! BPSW_isprime(VALUE(x))) { pari_warn(warner, "IFAC: pseudo-prime %Ps\n\tis not prime. PLEASE REPORT!\n", VALUE(x)); CLASS(x) = gen_0; } else { CLASS(x) = gen_1; /* prime (not proven if factor_proven = 0) */ res = 1; } if (DEBUGLEVEL>2) ifac_factor_dbg(x); return res; } /* sweep downward so we can with luck turn some Qs into Ps */ 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_isprime(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; CLASS(scan) = ifac_isprime(scan)? gen_1: gen_0; /* Qj | Ck */ } } /* 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) { 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(talker, "division by composite or finished prime in ifac_divide"); if (!VALUE(*where)) pari_err(talker, "division by nothing in ifac_divide"); #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 */ { INIT0(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) /* 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 cmp_res, hint = get_hint(partial); GEN factor, exponent; #ifdef IFAC_DEBUG ifac_check(*partial, *where); if (*where < *partial + 6) pari_err(talker, "'*where' out of bounds in ifac_crack"); if (!(VALUE(*where)) || typ(VALUE(*where)) != t_INT) pari_err(typeer, "ifac_crack"); if (CLASS(*where) != gen_0) pari_err(talker, "operand not known composite in ifac_crack"); #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 poowers even if MPQS is * blocked by hint: fast and useful in bounded factorization */ { ulong exp0 = 0, exp1 = 1, mask = 7; long good = 0; pari_sp av = avma; /* crack squares. Fast due to the initial square residue test */ 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 */ } /* At debug levels > 4, is_357_power() prints something more informative */ if (DEBUGLEVEL == 4) err_printf("IFAC: checking for odd power\n"); while ( (exp1 = is_357_power(VALUE(*where), &factor, &mask)) ) { good = 1; /* remember we succeeded once */ update_pow(*where, factor, exp1, &av); if (moebius_mode) return 0; /* no need to carry on */ } /* cutoff at 14 bits as trial division must have found everything below */ while ( (exp1 = is_pth_power(VALUE(*where), &factor, &exp0, 15)) ) { good = 1; /* remember we succeeded once */ update_pow(*where, factor, exp1, &av); if (moebius_mode) return 0; /* no need to carry on */ } if (good && hint != 15 && ifac_isprime(*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); /* 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(bugparier, "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(bugparier,"ifac_crack [Z_issquareall miss]"); return 2; } /* 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 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; } static GEN ifac_main(GEN *partial) { GEN here = ifac_find(*partial, *partial); long nf; if (!here) return gen_1; /* nothing left */ /* repeated factor in Moebius mode: stop. Shouldn't happen */ if (moebius_mode && EXPON(here) != gen_1) { if (DEBUGLEVEL >= 3) err_printf("IFAC: main loop: repeated old factor\n\t%Ps\n", *here); return gen_0; } /* 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); /* try defrag first */ if (here < *partial + 6) /* no luck */ ifac_realloc(partial, &here, 1); /* guaranteed to work */ } nf = ifac_crack(partial, &here); 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)) { 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_defrag(partial, &here); (void)ifac_resort(partial, &here); /* sort new cofactors down */ /* it doesn't matter whether this finds a repeated factor: we never * get to this point in Moebius mode */ ifac_defrag(partial, &here); /* resort may have created new gaps */ ifac_whoiswho(partial, &here, -1); } continue; } pari_err(talker, "non-existent factor class in ifac_main"); } /* 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. */ /* ifac_decomp: find primary factors of n until ifac_break() return true, or n * is factored if ifac_break is NULL. * * ifac_break: return 1: stop factoring, 0 continue. * * state is private data for ifac_break(), which must not leave anything on * the stack (except in state). * ifac_break is called in ifactor with here = NULL to register n, then * whenever a new factor is found. */ static long ifac_decomp(GEN n, long (*ifac_break)(GEN n,GEN pairs,GEN here,GEN state), GEN state, 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 == gen_1) 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); if (ifac_break && (*ifac_break)(n,pairs,here,state)) { if (DEBUGLEVEL >= 3) err_printf("IFAC: (Partial fact.)Stop requested.\n"); break; } INIT0(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; } /***********************************************************************/ /** **/ /** BASIC ARITHMETIC FUNCTIONS **/ /** **/ /***********************************************************************/ /* encapsulated functions; these call ifac_start() themselves, ensure stack * housekeeping etc. Call them on any large composite left over after trial * division, and multiply/add the result onto whatever you already have from * the small factors. */ static void ifac_memcheck(pari_sp av,pari_sp lim, GEN *part, GEN *here) { INIT0(*here); if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"ifac_xxx"); ifac_realloc(part, here, 0); *part = gerepileupto(av, *part); } } static void ifac_memcheck_extra(pari_sp av,pari_sp lim, GEN *part, GEN *here, GEN *extra, GEN res) { INIT0(*here); if (low_stack(lim, stack_lim(av,1))) { affii(*extra,res); *extra = res; 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(;;) { GEN here = ifac_main(&part); if (here == gen_0) { avma = av; return 0; } if (here == gen_1) { avma = av; return mu; } mu = -mu; ifac_memcheck(av, lim, &part, &here); } } static long ifac_omega(GEN n) { long omega = 0; pari_sp av = avma, lim = stack_lim(av,1); GEN part = ifac_start(n, 0); for(;;) { GEN here = ifac_main(&part); if (here == gen_1) { avma = av; return omega; } omega++; ifac_memcheck(av, lim, &part, &here); } } static long ifac_bigomega(GEN n) { long Omega=0; pari_sp av=avma, lim=stack_lim(av,1); GEN part = ifac_start(n, 0); for(;;) { GEN here = ifac_main(&part); if (here == gen_1) { avma = av; return Omega; } Omega += itos(EXPON(here)); ifac_memcheck(av, lim, &part, &here); } } static GEN euler_totient(GEN m, GEN p, long v) { m = mulii(m, addsi(-1, p)); if (v != 1) m = mulii(m, v == 2? p: powiu(p, v-1)); return m; } static GEN ifac_totient(GEN n) { GEN m = gen_1, phi = cgeti(lgefint(n)); pari_sp av=avma, lim=stack_lim(av,1); GEN part = ifac_start(n, 0); for(;;) { ulong v; GEN p, here = ifac_main(&part); if (here == gen_1) { avma = av; affii(m, phi); return phi; } p = VALUE(here); v = itou(EXPON(here)); m = euler_totient(m, p, v); ifac_memcheck_extra(av, lim, &part, &here, &m,phi); } } static GEN ifac_numdiv(GEN n) { GEN m = gen_1, tau = cgeti(lgefint(n)); pari_sp av=avma, lim=stack_lim(av,1); GEN part = ifac_start(n, 0); for(;;) { GEN here = ifac_main(&part); if (here == gen_1) { avma = av; affii(m, tau); return tau; } m = muliu(m, 1 + itou(EXPON(here))); ifac_memcheck_extra(av, lim, &part, &here, &m,tau); } return gerepileuptoint(av, tau); } /* 1 + p + ... + p^v, p != 2^BIL - 1 */ static GEN u_euler_sumdiv(GEN m, ulong p, long v) { GEN u = utoipos(1 + p); /* can't overflow */ for (; v > 1; v--) u = addsi(1, mului(p, u)); return mulii(m, u); } /* 1 + q + ... + q^v */ static GEN euler_sumdiv(GEN m, GEN q, long v) { GEN u = addsi(1, q); for (; v > 1; v--) u = addsi(1, mulii(q, u)); return mulii(m, u); } static GEN u_euler_sumdivk(GEN m, ulong p, long v, long k) { return euler_sumdiv(m, powuu(p,k), v); } static GEN euler_sumdivk(GEN m, GEN p, long v, long k) { return euler_sumdiv(m, powiu(p,k), v); } static GEN ifac_sumdivk(GEN n, long k) { GEN m = gen_1, S = cgeti(k * lgefint(n)+1); /* S < n^k (log n+1)^{k == 1} */ pari_sp av=avma, lim=stack_lim(av,1); GEN part = ifac_start(n, 0); for(;;) { long v; GEN p, here = ifac_main(&part); if (here == gen_1) { avma = av; affii(m, S); return S; } p = VALUE(here); v = itos(EXPON(here)); m = euler_sumdivk(m, p, v, k); ifac_memcheck_extra(av, lim, &part, &here, &m,S); } } /* where to stop trial dividing in factorization */ static 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 */ } 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; } GEN gmoebius(GEN n) { return map_proto_lG(moebius,n); } INLINE void chk_arith(GEN n) { if (typ(n) != t_INT) pari_err(arither1); if (!signe(n)) pari_err(talker, "zero argument in an arithmetic function"); } long moebius(GEN n) { byteptr d = diffptr+1; /* point at 3 - 2 */ pari_sp av = avma; ulong p, lim; long i, l, s, v; chk_arith(n); if (is_pm1(n)) return 1; if (equaliu(n, 2)) return -1; p = mod4(n); if (!p) return 0; if (p == 2) { s = -1; n = shifti(n, -1); } else { s = 1; n = icopy(n); } setabssign(n); lim = tridiv_bound(n); p = 2; while (p < lim) { int stop; if (!*d) break; NEXT_PRIME_VIADIFF(p,d); v = Z_lvalrem_stop(n, p, &stop); if (v > 1) { avma = av; return 0; } if (v) 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 > 1) { avma = av; return 0; } if (v) { s = -s; if (is_pm1(n)) { avma = av; return s; } } } if (BPSW_psp_nosmalldiv(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 */ } GEN gissquarefree(GEN x) { return map_proto_lG(issquarefree,x); } long Z_issquarefree(GEN n) { if (!signe(n)) return 0; 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(typeer,"issquarefree"); return 0; /* not reached */ } } GEN gomega(GEN n) { return map_proto_lG(omega,n); } long omega(GEN n) { byteptr d = diffptr+1; pari_sp av = avma; long i, l, nb, v; ulong p, lim; chk_arith(n); if (is_pm1(n)) return 0; v = vali(n); nb = v ? 1 : 0; n = shifti(n, -v); if (is_pm1(n)) return nb; setabssign(n); lim = tridiv_bound(n); p = 2; while (p < lim) { int stop; if (!*d) break; NEXT_PRIME_VIADIFF(p,d); v = Z_lvalrem_stop(n, p, &stop); if (v) nb++; if (stop) { avma = av; return is_pm1(n)? nb: nb+1; } } l = lg(primetab); for (i = 1; i < l; i++) { v = Z_pvalrem(n, gel(primetab,i), &n); if (v) { nb++; if (is_pm1(n)) { avma = av; return nb; } } } if (BPSW_psp_nosmalldiv(n)) { avma = av; return nb+1; } /* large composite without small factors */ nb += ifac_omega(n); avma = av; return nb; } GEN gbigomega(GEN n) { return map_proto_lG(bigomega,n); } long bigomega(GEN n) { byteptr d=diffptr+1; pari_sp av = avma; ulong p, lim; long i, l, nb, v; chk_arith(n); if (is_pm1(n)) return 0; nb = v = vali(n); n = shifti(n, -v); if (is_pm1(n)) { avma = av; return nb; } setabssign(n); lim = tridiv_bound(n); p = 2; while (p < lim) { int stop; if (!*d) break; NEXT_PRIME_VIADIFF(p,d); v = Z_lvalrem_stop(n, p, &stop); nb += v; if (stop) { avma = av; return is_pm1(n)? nb: nb+1; } } l = lg(primetab); for (i = 1; i < l; i++) { v = Z_pvalrem(n, gel(primetab,i), &n); if (v) { nb += v; if (is_pm1(n)) { avma = av; return nb; } } } if (BPSW_psp_nosmalldiv(n)) { avma = av; return nb+1; } nb += ifac_bigomega(n); avma = av; return nb; } GEN geulerphi(GEN n) { return map_proto_G(eulerphi,n); } ulong eulerphiu(ulong n) { byteptr d = diffptr+1; pari_sp av; ulong p, lim, m; long v; if (n == 1) return 1; v = vals(n); n >>= v; m = v > 1 ? 1UL << (v-1) : 1; if (n == 1) return m; lim = utridiv_bound(n); p = 2; while (p < lim) { int stop; if (!*d) break; NEXT_PRIME_VIADIFF(p,d); v = u_lvalrem_stop(&n, p, &stop); if (v) { m *= p-1; if (v > 1) m *= upowuu(p, v-1); } if (stop) { if (n != 1) m *= n-1; return m; } } if (uisprime_nosmalldiv(n)) return m*(n-1); av = avma; m *= itou( ifac_totient(utoipos(n)) ); avma = av; return m; } GEN eulerphi(GEN n) { byteptr d = diffptr+1; pari_sp av = avma; GEN m; ulong p, lim; long i, l, v; chk_arith(n); if (lgefint(n) == 3) return utoipos(eulerphiu((ulong)n[2])); v = vali(n); n = shifti(n,-v); setabssign(n); m = v > 1 ? int2n(v-1) : gen_1; if (is_pm1(n)) return gerepileuptoint(av,m); lim = tridiv_bound(n); p = 2; while (p < lim) { int stop; if (!*d) break; NEXT_PRIME_VIADIFF(p,d); v = Z_lvalrem_stop(n, p, &stop); if (v) { m = muliu(m, p-1); if (v > 2) m = mulii(m, powuu(p, v-1)); else if (v == 2) m = muliu(m, p); } if (stop) { if (!is_pm1(n)) m = mulii(m, addis(n,-1)); return gerepileuptoint(av,m); } } l = lg(primetab); for (i = 1; i < l; i++) { GEN p = gel(primetab,i); v = Z_pvalrem(n, p, &n); if (v) { m = euler_totient(m, p, v); if (is_pm1(n)) return gerepileuptoint(av,m); } } if (BPSW_psp_nosmalldiv(n)) return gerepileuptoint(av, mulii(m, addis(n,-1))); m = mulii(m, ifac_totient(n)); return gerepileuptoint(av,m); } GEN gnumbdiv(GEN n) { return map_proto_G(numbdiv,n); } GEN numbdiv(GEN n) { byteptr d = diffptr+1; pari_sp av = avma; GEN m; long i, l, v; ulong p, lim; chk_arith(n); if (is_pm1(n)) return gen_1; v = vali(n); n = shifti(n,-v); setabssign(n); m = utoipos(v+1); if (is_pm1(n)) return gerepileuptoint(av,m); lim = tridiv_bound(n); p = 2; while (p < lim) { int stop; if (!*d) break; NEXT_PRIME_VIADIFF(p,d); v = Z_lvalrem_stop(n, p, &stop); if (v) m = muliu(m, v+1); if (stop) { if (!is_pm1(n)) m = shifti(m,1); return gerepileuptoint(av,m); } } l = lg(primetab); for (i = 1; i < l; i++) { GEN p = gel(primetab,i); v = Z_pvalrem(n, p, &n); if (v) { m = muliu(m, 1 + v); if (is_pm1(n)) return gerepileuptoint(av,m); } } if(BPSW_psp_nosmalldiv(n)) return gerepileuptoint(av, shifti(m,1)); m = mulii(m, ifac_numdiv(n)); return gerepileuptoint(av,m); } GEN gsumdiv(GEN n) { return map_proto_G(sumdiv,n); } GEN sumdiv(GEN n) { byteptr d = diffptr+1; pari_sp av = avma, av2, limit; GEN m; ulong p, lim; long i, l, v; chk_arith(n); if (is_pm1(n)) return gen_1; v = vali(n); n = shifti(n,-v); setabssign(n); m = v ? addsi(-1, int2n(v+1)) : gen_1; if (is_pm1(n)) return gerepileuptoint(av,m); lim = tridiv_bound(n); p = 2; av2 = avma; limit = stack_lim(av2,3); while (p < lim) { int stop; if (!*d) break; NEXT_PRIME_VIADIFF(p,d); v = Z_lvalrem_stop(n, p, &stop); if (v) m = u_euler_sumdiv(m, p, v); if (low_stack(limit, stack_lim(av2,3))) { if(DEBUGMEM>1) pari_warn(warnmem,"sumdiv"); m = gerepileuptoint(av2, m); } if (stop) { if (!is_pm1(n)) m = euler_sumdiv(m, n, 1); goto end; } } l = lg(primetab); for (i = 1; i < l; i++) { GEN p = gel(primetab,i); v = Z_pvalrem(n, p, &n); if (v) { m = euler_sumdiv(m, p, v); if (is_pm1(n)) return gerepileuptoint(av,m); } } if(BPSW_psp_nosmalldiv(n)) { m = euler_sumdiv(m, n, 1); goto end; } m = mulii(m, ifac_sumdivk(n, 1)); end: return gerepileuptoint(av,m); } GEN gsumdivk(GEN n, long k) { return map_proto_GL(sumdivk,n,k); } GEN sumdivk(GEN n, long k) { byteptr d = diffptr+1; pari_sp av = avma, av2, limit; GEN n1, m; ulong p, lim; long i, l, k1, v; if (!k) return numbdiv(n); if (k == 1) return sumdiv(n); chk_arith(n); if (is_pm1(n)) return gen_1; k1 = k; n1 = n; if (k < 0) k = -k; if (k == 1) { m = sumdiv(n); goto fin; } v = vali(n); n = shifti(n,-v); setabssign(n); m = gen_1; while (v--) m = addsi(1,shifti(m,k)); if (is_pm1(n)) goto fin; lim = tridiv_bound(n); p = 2; av2 = avma; limit = stack_lim(av2,3); while (p < lim) { int stop; if (!*d) break; NEXT_PRIME_VIADIFF(p,d); v = Z_lvalrem_stop(n, p, &stop); if (v) m = u_euler_sumdivk(m, p, v, k); if (low_stack(limit, stack_lim(av2,3))) { if(DEBUGMEM>1) pari_warn(warnmem,"sumdiv"); m = gerepileuptoint(av2, m); } if (stop) { if (!is_pm1(n)) m = euler_sumdivk(m, n, 1, k); goto fin; } } l = lg(primetab); for (i = 1; i < l; i++) { GEN p = gel(primetab,i); v = Z_pvalrem(n, p, &n); if (v) { m = euler_sumdivk(m, p, v, k); if (is_pm1(n)) goto fin; } } if (BPSW_psp_nosmalldiv(n)) { m = euler_sumdivk(m, n, 1, k); goto fin; } m = mulii(m, ifac_sumdivk(n, k)); fin: if (k1 < 0) m = gdiv(m, powiu(n1,k)); return gerepileupto(av,m); } /***********************************************************************/ /** **/ /** COMPUTING THE MATRIX OF PRIME DIVISORS AND EXPONENTS **/ /** **/ /***********************************************************************/ static GEN aux_end(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--) { gel(E,i) = z; z += lg(z); gel(P,i) = z; z += lg(z); } gel(z,1) = P; gel(z,2) = E; return sort_factor(z, (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); } static int special_primes(GEN n, GEN pp, long *nb, GEN T) { long i, l = lg(T); 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; } /* all != 0 : only look for prime divisors < all */ static GEN ifactor(GEN n, long (*ifac_break)(GEN n, GEN pairs, GEN here, GEN state), GEN state, ulong all, long hint) { pari_sp av; long pp[] = { evaltyp(t_INT)|_evallg(4), 0,0,0 }; long nb = 0, i; ulong p, k, lim; byteptr d = diffptr+1; /* start at p = 3 */ i = signe(n); if (!i) { GEN z = cgetg(3,t_MAT); gel(z,1) = mkcol(gen_0); gel(z,2) = mkcol(gen_1); return z; } (void)cgetg(3,t_MAT); if (i < 0) STORE(&nb, utoineg(1), 1); if (is_pm1(n)) return aux_end(NULL,nb); n = gclone(n); setabssign(n); /* trial division bound */ if (all) { if (all > maxprime() + 1) pari_err(primer1, all); lim = all; /* use supplied limit */ } else lim = tridiv_bound(n); if (lim > 2) { 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(n,nb); } /* trial division */ p = 2; for(;;) { int stop; if (!*d) break; NEXT_PRIME_VIADIFF(p,d); if (p >= lim) break; k = Z_lvalrem_stop(n, p, &stop); if (k) STOREu(&nb, p, k); if (stop) { if (!is_pm1(n)) STOREi(&nb, n, 1); return aux_end(n,nb); } } /* pp = square of biggest p tried so far */ av = avma; affii(sqru(p), pp); avma = av; /* trial divide by the special primes */ if (special_primes(n, pp, &nb, primetab)) { if (!is_pm1(n)) STOREi(&nb, n, 1); return aux_end(n,nb); } if (all) { /* smallfact: look for easy pure powers then stop. Cf Z_isanypower */ GEN x = n, y; ulong mask = 7, ex0 = 11; long ex, k = 1; av = avma; while (Z_issquareall(x, &y)) { k <<= 1; x = y; } while ( (ex = is_357_power(x, &y, &mask)) ) { k *= ex; x = y; } /* stop when x^(1/k) < 2^14 */ while ( (ex = is_pth_power(x, &y, &ex0, 15)) ) { k *= ex; x = y; } if (k > 1) affii(x, n); avma = av; STOREi(&nb, n, k); if (DEBUGLEVEL >= 2) { pari_warn(warner, "IFAC: untested integer declared prime"); err_printf("\t%Ps\n", n); } return aux_end(n,nb); } /* test primality */ if (BPSW_psp_nosmalldiv(n)) { STOREi(&nb, n, 1); return aux_end(n,nb); } /* now we have a large composite */ if (ifac_break && (*ifac_break)(n,NULL,NULL,state)) /*initialize ifac_break*/ { if (DEBUGLEVEL>2) err_printf("IFAC: (Partial fact.) Initial stop requested.\n"); } else nb += ifac_decomp(n, ifac_break, state, hint); return aux_end(n, nb); } /* state[1]: current unfactored part. * state[2]: limit. */ static long ifac_break_limit(GEN n, GEN pairs/*unused*/, GEN here, GEN state) { pari_sp ltop = avma; GEN N; int res; (void)pairs; if (!here) /* initial call */ /*Small primes have been removed, n is the new unfactored part.*/ N = n; else { GEN q = powii(VALUE(here),EXPON(here)); /* primary factor found.*/ if (DEBUGLEVEL>2) err_printf("IFAC: Stop: Primary factor: %Ps\n",q); N = diviiexact(gel(state,1),q); /* divide unfactored part by q */ } affii(N, gel(state,1)); /* affect()ed to state[1] to preserve stack. */ if (DEBUGLEVEL>2) err_printf("IFAC: Stop: remaining %Ps\n",state[1]); /* check the stopping criterion, then restore stack */ res = cmpii(gel(state,1),gel(state,2)) <= 0; avma = ltop; return res; } /* see before ifac_crack() in ifactor1.c for current semantics of 'hint' (factorint's 'flag') */ GEN factorint(GEN n, long flag) { if (typ(n) != t_INT) pari_err(arither1); return ifactor(n,NULL,NULL, 0,flag); } GEN Z_factor_limit(GEN n, ulong all) { if (!all) all = maxprime() + 1; return ifactor(n,NULL,NULL, all,decomp_default_hint); } GEN Z_factor(GEN n) { return ifactor(n,NULL,NULL, 0,decomp_default_hint); } int is_Z_factor(GEN f) { long i, l; GEN P, E; if (typ(f) != t_MAT || lg(f) != 3) return 0; P = gel(f,1); E = gel(f,2); l = lg(P); for (i = 1; i < l; i++) { GEN p = gel(P,i), e = gel(E,i); if (typ(p) != t_INT || signe(p) <= 0 || typ(e) != t_INT || signe(e) <= 0) return 0; } return 1; } /* 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) { GEN state = cgetg(3,t_VEC); /* icopy is mainly done to allocate memory for affect(). * Currently state[1] is discarded in initial call to ifac_break_limit */ gel(state,1) = icopy(n); gel(state,2) = gcopy(limit); return ifactor(n, &ifac_break_limit, state, 0, decomp_default_hint); } pari-2.5.5/src/basemath/RgX.c0000644000175000017500000011704012147140046014325 0ustar billbill/* $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. */ #include "pari.h" #include "paripriv.h" 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; } long RgX_equal_var(GEN x, GEN y) { return varn(x) == varn(y) && RgX_equal(x,y); } /* Returns 1 in the base ring over which x is defined */ /* HACK: this also works for t_SER */ GEN RgX_get_1(GEN x) { pari_sp av = avma; GEN p, T; long i, lx, vx = varn(x), 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: x = mkintmod(gen_1,p); break; case t_PADIC: x = cvtop(gen_1, p, lx); break; case t_FFELT: x = FF_1(T); break; default: x = gen_1; break; } return gerepileupto(av, scalarpol(x, vx)); } /* Returns 0 in the base ring over which x is defined */ /* HACK: this also works for t_SER */ GEN RgX_get_0(GEN x) { pari_sp av = avma; GEN p, T; long i, lx, vx = varn(x), 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: x = mkintmod(gen_0,p); break; case t_PADIC: x = cvtop(gen_0, p, lx); break; case t_FFELT: x = FF_zero(T); break; default: x = gen_0; break; } return gerepileupto(av, scalarpol(x, vx)); } /********************************************************************/ /** **/ /** COMPOSITION **/ /** **/ /********************************************************************/ static GEN RgXQ_eval_powers(GEN P, GEN V, long a, long n) { GEN z = scalarpol(gel(P,2+a), varn(P)); /* V[1] = 1 */ long i; for (i=1; i<=n; i++) z = RgX_add(z, RgX_Rg_mul(gel(V,i+1), gel(P,2+a+i))); return z; } /* Brent & Kung * (Fast algorithms for manipulating formal power series, JACM 25:581-595, 1978) * * V as output by RgXQ_powers(x,l,T,p). For optimal performance, l is as given * by brent_kung_optpow */ GEN RgX_RgXQV_eval(GEN P, GEN V, GEN T) { pari_sp av = avma, btop; long l = lg(V)-1, d = degpol(P); GEN z, u; if (d < 0) return pol_0(varn(T)); if (d < l) { z = RgXQ_eval_powers(P,V,0,d); return gerepileupto(av, z); } if (l<=1) pari_err(talker,"powers is only [] or [1] in RgX_RgXQV_eval"); d -= l; btop = avma; z = RgXQ_eval_powers(P,V,d+1,l-1); while (d >= l-1) { d -= l-1; u = RgXQ_eval_powers(P,V,d+1,l-2); z = RgX_add(u, RgXQ_mul(z, gel(V,l), T)); z = gerepileupto(btop, z); } u = RgXQ_eval_powers(P,V,0,d); z = RgX_add(u, RgXQ_mul(z, gel(V,d+2), T)); if (DEBUGLEVEL>=8) { long cnt = 1 + (degpol(P) - l) / (l-1); err_printf("RgX_RgXQV_eval: %ld RgXQ_mul [%ld]\n", cnt, l-1); } return gerepileupto(av, z); } /* Q in Z[X] and x in Rg[X]/(T). Return a lift of Q(x) */ GEN RgX_RgXQ_eval(GEN Q, GEN x, GEN T) { pari_sp av = avma; GEN z; long d = degpol(Q), rtd; if (typ(Q)!=t_POL || typ(x)!=t_POL) pari_err(typeer,"RgX_RgXQ_eval"); if (d < 0) return pol_0(varn(Q)); rtd = (long) sqrt((double)d); z = RgX_RgXQV_eval(Q, RgXQ_powers(x, rtd, T), T); return gerepileupto(av, z); } 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(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) return x0; if (dx < 0) return pol_0(varn(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) z[i] = 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; 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) z[id] = 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 gcopy(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 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 gcopy(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 */ static GEN RgXQ_to_mod(GEN x, GEN T) { long d; switch(typ(x)) { case t_INT: case t_FRAC: return gcopy(x); default: d = degpol(x); if (d < 0) return gen_0; if (d == 0) return gcopy(gel(x,2)); return mkpolmod(gcopy(x), T); } } /* T a ZX, z lifted from (Q[Y]/(T(Y)))[X], apply RgXQ_to_mod to all coeffs. * Not memory clean because T not copied */ static GEN RgXQX_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 P(Y,X), n is an upper bound for deg_Y(P) */ GEN RgXY_swap(GEN x, long n, long w) { long j, lx = lg(x), ly = n+3, v = varn(x); GEN y = cgetg(ly, t_POL); y[1] = evalsigne(1) | evalvarn(v); for (j=2; j 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(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; 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, y != 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 = (a>nx)? ny+2: 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 gcopy(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; } /* 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); lz = (nx << 1) + 1, nz = lz-2; lz += v; z = cgetg(lz,t_POL) + 2; for (i=0; i>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); } 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): gcopy(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(gdiver); 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 gcopy(x); if (pr == ONLY_DIVIDES) return signe(x)? NULL: pol_0(varn(x)); z = pol_0(varn(x)); if (pr) *pr = gcopy(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); 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 = 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(gdiver); 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 gcopy(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; } /* 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(gdiver); 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 gcopy(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--; gel(z,iz++) = gen_0; } if (dx < dy) break; if (low_stack(lim,stack_lim(av2,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"RgX_pseudodivrem dx = %ld >= %ld",dx,dy); gerepilecoeffs2(av2,x,dx+1, z,iz); } } 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 -= 2; z[0] = evaltyp(t_POL) | evallg(lz); z[1] = evalsigne(1) | evalvarn(vx); 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; if (isrationalzero(x)) return pol_0(varn(y)); 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; if (!x) return pol_0(varn(y)); 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 _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); } /* 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 gcopy(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): gcopy(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) { GEN V=cgetg(l+2,t_VEC); long i; gel(V,1) = pol_1(varn(T)); if (l==0) return V; gel(V,2) = gcopy(x); if (l==1) return V; gel(V,3) = RgXQ_sqr(x,T); if ((degpol(x)<<1) < degpol(T)) { for(i = 4; i < l+2; i++) gel(V,i) = RgXQ_mul(gel(V,i-1),x,T); } else { /* use squarings if degree(x) is large */ for(i = 4; i < l+2; i++) gel(V,i) = (i&1)? RgXQ_sqr(gel(V, (i+1)>>1),T) : RgXQ_mul(gel(V, i-1),x,T); } return V; } /* 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; } 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) || dx < 0) return y; return gerepileupto(av, gdiv(y, gpowgs(L, dx))); } pari-2.5.5/src/basemath/QX_factor.c0000644000175000017500000007472412147140046015526 0ustar billbill/* $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. */ #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--) { 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; if (!i) break; } 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(3); /* 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); uGEN trace1 = (uGEN)cgetg(lfamod+1, t_VECSMALL); uGEN trace2 = (uGEN)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_COL); GEN fa = cgetg(lfamod+1, t_COL); *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 { famod[k] = 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; } /* 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; long e,i,fl; GEN q,pow2, r = y; if (typ(B) != t_INT) B = ceil_safe(B); if (expi(B) <= (expi(y) << 6)) /* 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); } } /* binary splitting: compute bits of e one by one */ /* compute pow2[i] = y^(2^i) [i < very crude upper bound for log_2(n)] */ pow2 = new_chunk(bit_accuracy(lgefint(B))); gel(pow2,0) = y; for (i=0,q=r;; ) { fl = cmpii(r,B); if (fl >= 0) break; q = r; r = sqri(q); i++; gel(pow2,i) = r; } if (i == 0) { e = 1; goto END; } /* y <= B */ for (i--, e=1L< 0) e++; break; } r = mulii(q, gel(pow2,i)); fl = cmpii(r, B); if (fl <= 0) { e += (1L< 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 = lg(H[1]); 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_COL); 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(bugparier,"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++) p1[j] = 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 = mkcol(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 pol(0) != 0, polp = pol/lc(pol) mod p. * Return vector of rational roots of a */ GEN DDF_roots(GEN pol, GEN polp, GEN p) { GEN lc, lcpol, z, pe, pes2, bound; long i, m, e, lz, v = varn(pol); pari_sp av, lim; pari_timer T; if (DEBUGLEVEL>2) timer_start(&T); lc = absi(leading_term(pol)); if (is_pm1(lc)) lc = NULL; lcpol = lc? ZX_Z_mul(pol, lc): pol; bound = root_bound(pol); if (lc) bound = mulii(lc, bound); e = logint(addis(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 = FpX_roots(polp, p); lz = lg(z)-1; if (lz > (degpol(pol) >> 2)) { /* many roots */ z = shallowconcat(deg1_from_roots(z, v), FpX_div(polp, FpV_roots_to_pol(z, p, v), p)); z = ZpX_liftfact(pol, z, NULL, p, e, pe); } else { z = ZpX_liftroots(pol, z, p, e); z = deg1_from_roots(z, v); } if (DEBUGLEVEL>2) timer_printf(&T, "Hensel lift (mod %Ps^%ld)", p,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 = pol = q; r = negi( constant_term(y) ); if (lc) { r = gdiv(r,lc); pol = Q_primpart(pol); lc = absi( leading_term(pol) ); if (is_pm1(lc)) lc = NULL; else lcpol = ZX_Z_mul(pol, 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, &pol, &lc, &lcpol); } } if (DEBUGLEVEL>2) timer_printf(&T, "Recombination"); z[0] = evaltyp(t_VEC) | evallg(m); return z; } /* Assume a squarefree, degree(a) > 0, a(0) != 0. * If fl != 0 look only for rational roots */ static GEN DDF(GEN a, int fl) { GEN lead, prime, famod, z, ap; const long da = degpol(a); long chosenp, p, nfacp, np, nmax, ti = 0; pari_sp av = avma, av1; byteptr pt = diffptr; const long MAXNP = 7; pari_timer T, T2; if (DEBUGLEVEL>2) { timer_start(&T); timer_start(&T2); } nmax = da+1; chosenp = 0; lead = gel(a,da+2); if (equali1(lead)) lead = NULL; av1 = avma; for (p = np = 0; np < MAXNP; avma = av1) { NEXT_PRIME_VIADIFF_CHECK(p,pt); if (lead && !smodis(lead,p)) continue; z = ZX_to_Flx(a, p); if (!Flx_is_squarefree(z, p)) continue; nfacp = fl? Flx_nbroots(z, p): Flx_nbfact(z, p); if (DEBUGLEVEL>4) err_printf("...tried prime %3ld (%-3ld %s). Time = %ld\n", p, nfacp, fl?"roots": "factors", timer_delay(&T2)); if (nfacp < nmax) { if (nfacp <= 1) { if (!fl) { avma = av; return mkcol(a); } /* irreducible */ if (!nfacp) return cgetg(1, t_VEC); /* no root */ } nmax = nfacp; chosenp = p; if (da > 100 && nmax < 5) break; /* large degree, few factors. Enough */ } np++; } prime = utoipos(chosenp); ap = lead? FpX_normalize(a, prime): FpX_red(a, prime); if (fl) return gerepilecopy(av, DDF_roots(a, ap, prime)); famod = cgetg(nmax+1,t_COL); gel(famod,1) = ap; if (nmax != FpX_split_Berlekamp((GEN*)(famod+1), prime)) pari_err(bugparier,"DDF: wrong numbers of factors"); if (DEBUGLEVEL>2) { if (DEBUGLEVEL>4) timer_printf(&T2, "splitting mod p = %ld", chosenp); ti = timer_delay(&T); err_printf("Time setup: %ld\n", ti); } z = combine_factors(a, famod, prime, da-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, 0); 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, W, P, e; long i, k, dW, 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++) { W = ZX_gcd_all(T,V, &T); dW = degpol(W); /* W = prod P^e, e > k; V = prod P^e, e >= k */ if (dW != degpol(V)) { gel(P,i) = Q_primpart(RgX_div(V,W)); e[i] = k; i++; } if (dW <= 0) 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, qp, H, Hp, g, Ag, Bg; long m, n, valX, valA, vA = varn(A); ulong p; pari_sp ltop, av, avlim; byteptr d; 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); } av = avma; avlim = stack_lim(av, 1); H = NULL; d = init_modular(&p); for(;;) { NEXT_PRIME_VIADIFF_CHECK(p,d); 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); } qp = muliu(q,p); if (!ZX_incremental_CRT(&H, Hp, q, qp, p)) { q = qp; continue; } /* H stable: check divisibility */ q = qp; if (!ZX_divides(Bg, H)) continue; R = ZX_divides(Ag, H); if (!R) continue; 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); } pari-2.5.5/src/basemath/base5.c0000644000175000017500000006357412147140046014640 0ustar billbill/* $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. */ /*******************************************************************/ /* */ /* BASIC NF OPERATIONS */ /* (continued 2) */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" static GEN _checkrnfeq(GEN x) { if (typ(x) == t_VEC) switch(lg(x)) { case 13: /* checkrnf(x); */ return gel(x,11); case 4: return x; } return NULL; } GEN checkrnfeq(GEN x) { x = _checkrnfeq(x); if (!x) pari_err(talker,"please apply rnfequation(,,1)"); return x; } GEN eltreltoabs(GEN rnfeq, GEN x) { long i, k, va; pari_sp av = avma; GEN polabs, teta, alpha, s; rnfeq = checkrnfeq(rnfeq); polabs= gel(rnfeq,1); alpha = lift_intern(gel(rnfeq,2)); k = itos(gel(rnfeq,3)); va = varn(polabs); if (varncmp(gvar(x), va) > 0) x = scalarpol(x,va); /* Mod(X - k alpha, polabs(X)), alpha root of the polynomial defining base */ teta = gadd(pol_x(va), gmulsg(-k,alpha)); s = gen_0; for (i=lg(x)-1; i>1; i--) { GEN c = gel(x,i); long tc = typ(c); switch(tc) { case t_POLMOD: c = gel(c,2); if (typ(c) != t_POL) break; c = RgX_RgXQ_eval(c, alpha, polabs); break; case t_POL: c = RgX_RgXQ_eval(c, alpha, polabs); break; default: if (!is_const_t(tc)) pari_err(talker, "incorrect data in eltreltoabs"); } s = RgX_rem(gadd(c, gmul(teta,s)), polabs); } return gerepileupto(av, s); } /* x a t_VEC of rnf elements in 'alg' form */ static GEN modulereltoabs(GEN rnf, GEN x) { GEN W = gel(x,1), I = gel(x,2), nf = gel(rnf,10), rnfeq = gel(rnf,11); GEN M, basnf, cobasnf, T = nf_get_pol(nf), polabs = gel(rnfeq,1); long i, j, k, n = lg(W)-1, m = degpol(T); M = cgetg(n*m+1, t_VEC); basnf = lift_intern( gsubst(nf_get_zk(nf), varn(T), gel(rnfeq,2)) ); basnf = Q_primitive_part(basnf, &cobasnf); /* remove denom. --> faster */ 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,cobasnf)); if (typ(id) == t_INT) for (j=1; j<=m; j++) { GEN z = RgX_rem(gmul(w, gel(basnf,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(gmul(basnf,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; } static GEN makenfabs(GEN rnf) { GEN M, d, rnfeq, pol, nf, NF = zerovec(9); long n; rnfeq = gel(rnf,11); pol = gel(rnfeq,1); nf = gel(rnf,10); M = modulereltoabs(rnf, gel(rnf,7)); n = degpol(pol); M = RgXV_to_RgM(Q_remove_denom(M, &d), n); if (d) M = RgM_Rg_div(ZM_hnfmodall(M, d, hnf_MODID|hnf_CENTER), d); else M = matid(n); gel(NF,1) = pol; gel(NF,3) = mulii(powiu(nf_get_disc(nf), rnf_get_degree(rnf)), idealnorm(nf, gel(rnf,3))); nf_set_multable(NF, M, NULL); /* possibly wrong, but correct prime divisors [for idealprimedec] */ gel(NF,4) = Q_denom(gel(NF,7)); return NF; } static GEN makenorms(GEN rnf) { GEN f = gel(rnf,4); 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 check_and_build_obj(rnf, NFABS, &makenfabs); } GEN check_and_build_norms(GEN rnf) { return check_and_build_obj(rnf, NORMS, &makenorms); } GEN rnfinit(GEN nf, GEN pol) { pari_sp av = avma; GEN rnf, bas, D,d,f, B; nf = checknf(nf); bas = rnfallbase(nf,&pol, &D,&d, &f); B = matbasistoalg(nf,gel(bas,1)); gel(bas,1) = lift_if_rational( RgM_to_RgXV(B,varn(pol)) ); rnf = cgetg(13, t_VEC); gel(rnf,1) = pol; gel(rnf,2) = cgetg(1, t_VEC); /* dummy */ 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) = rnfequation2(nf,pol); gel(rnf,12) = gen_0; return gerepilecopy(av, rnf); } GEN rnfelementreltoabs(GEN rnf,GEN x) { long i, lx; GEN z; switch(typ(x)) { case t_VEC: case t_COL: case t_MAT: z = cgetg_copy(x, &lx); for (i=1; i 3) pari_err(talker,"element is not in the base field in rnfelementdown"); z = gel(z,2); } return gerepilecopy(av, z); default: return gcopy(x); } } /* x est exprime sur la base relative */ static GEN rnfprincipaltohermite(GEN rnf,GEN x) { pari_sp av = avma; GEN bas = gel(rnf,7), nf = gel(rnf,10); x = rnfbasistoalg(rnf,x); x = rnfalgtobasis(rnf, gmul(x, gmodulo(gel(bas,1), gel(rnf,1)))); settyp(x, t_MAT); return gerepileupto(av, nfhnf(nf, mkvec2(x, gel(bas,2)))); } GEN rnfidealhermite(GEN rnf, GEN x) { GEN z, nf, bas; checkrnf(rnf); nf = gel(rnf,10); switch(typ(x)) { case t_INT: case t_FRAC: bas = gel(rnf,7); 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(x[1]) == t_MAT) return nfhnf(nf, x); return rnfidealabstorel(rnf, x); case t_POLMOD: case t_POL: case t_COL: return rnfprincipaltohermite(rnf,x); } pari_err(typeer,"rnfidealhermite"); 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 polymods) */ GEN rnfidealtwoelement(GEN rnf, GEN x) { pari_sp av = avma; GEN y, z, NF; checkrnf(rnf); NF = check_and_build_nfabs(rnf); y = rnfidealreltoabs(rnf,x); y = matalgtobasis(NF, y); settyp(y, t_MAT); y = idealtwoelt(NF, ZM_hnf(y)); z = rnfelementabstorel(rnf, gmul(gel(NF,7), gel(y,2))); return gerepilecopy(av, mkvec2(gel(y,1), z)); } GEN rnfidealmul(GEN rnf,GEN x,GEN y) /* x et y sous HNF relative uniquement */ { pari_sp av = avma; GEN z, nf, x1, x2, p1, p2; z = rnfidealtwoelement(rnf,y); nf = gel(rnf,10); x = rnfidealhermite(rnf,x); x1 = gmodulo(gmul(gmael(rnf,7,1), matbasistoalg(nf,gel(x,1))),gel(rnf,1)); x2 = gel(x,2); p1 = gmul(gel(z,1), gel(x,1)); p2 = rnfalgtobasis(rnf, gmul(gel(z,2), x1)); settyp(p2, t_MAT); 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(constpoler,"rnfequation"); RgX_check_ZX(A,"rnfequation"); } B = rnf_fix_pol(A,B,1); lB = lg(B); if (lB<=3) pari_err(constpoler,"rnfequation"); B = Q_primpart(B); RgX_check_ZXY(B,"rnfequation"); if (!nfissquarefree(A,B)) pari_err(talker,"inseparable relative equation in rnfequation"); *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); } 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(lg(M[1])-1, 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; MCS[k] = 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(typeer,"rnfpolred"); 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); } /* Let K = Q[X]/T = nf. Given a relative polynomial pol in K[X], L = K[X]/(pol), * compute a pseudo-basis for Z_L, then an absolute basis */ static GEN makebasis(GEN nf, GEN pol, GEN rnfeq) { GEN T = nf_get_pol(nf), TAB = gel(nf,9), W, I, polabs, a, B, ZK, p1, den, A; pari_sp av = avma; long i, j, k, N = degpol(pol), n = degpol(T), nN = n*N; polabs= gel(rnfeq,1); /* in Z[X], L = Q[X] / polabs, and pol | polabs */ a = gel(rnfeq,2); a = lift_intern(a); /* root of T in Q[X]/polabs */ p1 = rnfpseudobasis(nf,pol); W = gel(p1,1); I = gel(p1,2); if (DEBUGLEVEL>1) err_printf("relative basis computed\n"); A = QXQ_powers(a, n-1, polabs); /* ZK = integer basis of K, as elements of L */ ZK = RgV_RgM_mul(A, RgXV_to_RgM(nf_get_zk(nf),n)); W = RgV_RgM_mul(pol_x_powers(N, varn(pol)), W); /* vector of nfX */ B = cgetg(nN+1, t_MAT); for(i=k=1; i<=N; i++) { GEN w = gel(W,i), id = gel(I,i); if (typ(id) == t_MAT) { w = typ(w) == t_COL? tablemulvec(TAB, w, id): RgM_Rg_mul(id,w); for(j=1; j<=n; j++) { p1 = grem(RgV_dotproduct(ZK, gel(w,j)), polabs); gel(B,k++) = RgX_to_RgV(p1, nN); } } else { /* scalar */ if (typ(id) != t_INT || !is_pm1(id)) w = gmul(w, id); for(j=1; j<=n; j++) { p1 = grem(gmul(gel(ZK,j), w), polabs); gel(B,k++) = RgX_to_RgV(p1, nN); } } } B = Q_remove_denom(B, &den); if (den) { B = ZM_hnfmodid(B, den); B = RgM_Rg_div(B, den); } else B = matid(nN); return gerepilecopy(av, mkvec2(polabs, B)); } /* relative polredabs. Returns relative polynomial by default (flag = 0) * flag & nf_ORIG: + element (base change) * flag & nf_ADDZK: + integer basis * flag & nf_ABSOLUTE: absolute polynomial */ GEN rnfpolredabs(GEN nf, GEN relpol, long flag) { pari_timer ti; GEN red, bas, elt, pol, T, a; long fl = (flag & nf_ADDZK)? nf_ADDZK: nf_RAW; pari_sp av = avma; if (typ(relpol)!=t_POL) pari_err(typeer,"rnfpolredabs"); nf = checknf(nf); if (DEBUGLEVEL>1) timer_start(&ti); T = nf_get_pol(nf); relpol = rnf_fix_pol(T, relpol, 0); if ((flag & nf_ADDZK) && !(flag & nf_ABSOLUTE)) pari_err(impl,"this combination of flags in rnfpolredabs"); if (flag & nf_PARTIALFACT) { long sa; fl |= nf_PARTIALFACT; bas = rnfequationall(nf, relpol, &sa, NULL); a = stoi(sa); } else { GEN eq = rnfequation2(nf,relpol), rel; a = gel(eq,3); /* relpol( X + Mod(-a y, T(y)) )*/ rel = RgXQX_translate(relpol, deg1pol_shallow(negi(a),gen_0,varn(T)), T); bas = makebasis(nf, rel, eq); if (DEBUGLEVEL>1) { timer_printf(&ti, "absolute basis"); err_printf("original absolute generator: %Ps\n", gel(eq,1)); } } red = polredabs0(bas, fl); pol = gel(red,1); if (DEBUGLEVEL>1) err_printf("reduced absolute generator: %Ps\n",pol); if (flag & nf_ABSOLUTE) return gerepilecopy(av, (flag & nf_ADDZK)? red: pol); elt = RgXQX_translate(gel(red,2), deg1pol_shallow(a,gen_0,varn(T)), T); elt = rnf_fix_pol(T, elt, 0); pol = RgXQ_charpoly(elt, relpol, varn(relpol)); pol = lift_if_rational(pol); if (flag & nf_ORIG) pol = mkvec2(pol, mkpolmod(RgXQ_reverse(elt,relpol),pol)); return gerepilecopy(av, pol); } pari-2.5.5/src/basemath/bibli2.c0000644000175000017500000014130712200714311014763 0ustar billbill/* $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. */ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /** **/ /** SPECIAL POLYNOMIALS **/ /** **/ /*******************************************************************/ #ifdef LONG_IS_64BIT static const long SQRTVERYBIGINT = 3037000500L; /* ceil(sqrt(LONG_MAX)) */ #else static const long SQRTVERYBIGINT = 46341L; #endif /* Tchebichev polynomial: T0=1; T1=X; T(n)=2*X*T(n-1)-T(n-2) * T(n) = (n/2) sum_{k=0}^{n/2} a_k x^(n-2k) * where a_k = (-1)^k 2^(n-2k) (n-k-1)! / k!(n-2k)! is an integer * and a_0 = 2^(n-1), a_k / a_{k-1} = - (n-2k+2)(n-2k+1) / 4k(n-k) */ GEN polchebyshev1(long n, long v) /* Assume 4*n < LONG_MAX */ { long k, l; pari_sp av; GEN q,a,r; if (v<0) v = 0; /* polchebyshev(-n,1) = polchebyshev(n,1) */ if (n < 0) n = -n; if (n==0) return pol_1(v); if (n==1) return pol_x(v); q = cgetg(n+3, t_POL); r = q + n+2; a = int2n(n-1); gel(r--,0) = a; gel(r--,0) = gen_0; if (n < SQRTVERYBIGINT) for (k=1,l=n; l>1; k++,l-=2) { av = avma; a = diviuexact(muliu(a, l*(l-1)), 4*k*(n-k)); togglesign(a); a = gerepileuptoint(av, a); gel(r--,0) = a; gel(r--,0) = gen_0; } else for (k=1,l=n; l>1; k++,l-=2) { av = avma; a = diviiexact(mulii(a, muluu(l, l-1)), muluu(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; if (n < SQRTVERYBIGINT) for (m=1; 2*m<= n; m++) { av = avma; a = diviuexact(muliu(a, (n-2*m+2)*(n-2*m+1)), 4*m*(n-m+1)); togglesign(a); a = gerepileuptoint(av, a); gel(r--,0) = a; gel(r--,0) = gen_0; } else for (m=1; 2*m<= n; m++) { av = avma; a = diviiexact(mulii(a, muluu(n-2*m+2, n-2*m+1)), muluu(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(flagerr, "polchebyshev"); } return NULL; /* not reached */ } GEN polchebyshev_eval(long n, long kind, GEN x) { if (!x) return polchebyshev(n, kind, 0); if (gcmpX(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(flagerr, "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(talker,"negative degree in hermite"); 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; if (n < SQRTVERYBIGINT) for (m=1; 2*m<= n; m++) { av = avma; a = diviuexact(muliu(a, (n-2*m+2)*(n-2*m+1)), 4*m); togglesign(a); gel(r--,0) = a = gerepileuptoint(av, a); gel(r--,0) = gen_0; } else for (m=1; 2*m<= n; m++) { av = avma; a = diviuexact(mulii(a, muluu(n-2*m+2, n-2*m+1)), 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) { pari_sp av; long m; GEN a, x2, T; if (!x) return polhermite(n, 0); if (gcmpX(x)) return polhermite(n, varn(x)); if (n==0) return gen_1; av = avma; x2 = gsqr(x); T = a = int2n(n); if (n < SQRTVERYBIGINT) for (m=1; 2*m<= n; m++) { T = gmul(T, x2); av = avma; a = diviuexact(muliu(a, (n-2*m+2)*(n-2*m+1)), 4*m); togglesign(a); T = gadd(T, a); } else for (m=1; 2*m<= n; m++) { T = gmul(T, x2); av = avma; a = diviuexact(mulii(a, muluu(n-2*m+2, n-2*m+1)), 4*m); togglesign(a); T = gadd(T, a); } if (odd(n)) T = gmul(T,x); return gerepileupto(av, T); } /* Legendre polynomial * L0=1; L1=X; (n+1)*L(n+1)=(2*n+1)*X*L(n)-n*L(n-1) * L(n) = 2^-n sum_{k=0}^{n/2} a_k x^(n-2k) * where a_k = (-1)^k (2n-2k)! / k! (n-k)! (n-2k)! is an integer * and a_0 = binom(2n,n), a_k / a_{k-1} = - (n-2k+1)(n-2k+2) / 2k (2n-2k+1) */ GEN pollegendre(long n, long v) { long k, l; pari_sp av; GEN a, r, q; if (v<0) v = 0; /* pollegendre(-n) = pollegendre(n-1) */ if (n < 0) n = -n-1; if (n==0) return pol_1(v); if (n==1) return pol_x(v); av = avma; q = cgetg(n+3, t_POL); r = q + n+2; gel(r--,0) = a = binomialuu(n<<1,n); gel(r--,0) = gen_0; if (n < SQRTVERYBIGINT) for (k=1,l=n; l>1; k++,l-=2) { /* l = n-2*k+2 */ av = avma; a = diviuexact(muliu(a, l*(l-1)), 2*k*(n+l-1)); togglesign(a); a = gerepileuptoint(av, a); gel(r--,0) = a; gel(r--,0) = gen_0; } else for (k=1,l=n; l>1; k++,l-=2) { /* l = n-2*k+2 */ av = avma; a = diviiexact(mulii(a, muluu(l, l-1)), muluu(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 k, l; pari_sp av; GEN T, a, x2; if (!x) return pollegendre(n, 0); if (gcmpX(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; x2 = gsqr(x); T = a = binomialuu(n<<1,n); if (n < SQRTVERYBIGINT) for (k=1,l=n; l>1; k++,l-=2) { /* l = n-2*k+2 */ T = gmul(T, x2); av = avma; a = diviuexact(muliu(a, l*(l-1)), 2*k*(n+l-1)); togglesign(a); a = gerepileuptoint(av, a); T = gadd(T, a); } else for (k=1,l=n; l>1; k++,l-=2) { /* l = n-2*k+2 */ T = gmul(T, x2); av = avma; a = diviiexact(mulii(a, muluu(l, l-1)), muluu(2*k, n+l-1)); togglesign(a); a = gerepileuptoint(av, a); T = gadd(T, a); } if (odd(n)) T = gmul(T,x); return gerepileupto(av, gmul2n(T,-n)); } /* polcyclo(p) = X^(p-1) + ... + 1 */ static GEN polcyclo_prime(long p, long v) { GEN T = cgetg(p+2, t_POL); long i; T[1] = evalsigne(1) | evalvarn(v); for (i = 2; i < p+2; i++) gel(T,i) = gen_1; return T; } /* cyclotomic polynomial */ GEN polcyclo(long n, long v) { long s, q, i, l; pari_sp av=avma; GEN T, P; if (n <= 0) pari_err(talker, "argument must be positive in polcyclo"); if (v<0) v = 0; if (n == 1) return deg1pol_shallow(gen_1, gen_m1, v); P = gel(factoru(n), 1); l = lg(P); s = P[1]; T = polcyclo_prime(s, v); for (i = 2; i < l; i++) { /* Phi_{np}(X) = Phi_n(X^p) / Phi_n(X) */ s *= P[i]; T = RgX_div(RgX_inflate(T, P[i]), T); } /* s = squarefree part of n */ q = n / s; if (q == 1) return gerepileupto(av, T); return gerepilecopy(av, RgX_inflate(T,q)); } /* cyclotomic polynomial */ GEN polcyclo_eval(long n, GEN x) { pari_sp av= avma; GEN P, md, xd, yn, yd; long l, s, i, j, q, mu, tx; if (!x) return polcyclo(n, 0); tx = typ(x); if (gcmpX(x)) return polcyclo(n, varn(x)); if (n <= 0) pari_err(talker, "argument must be positive in polcyclo"); if (n == 1) return gsubgs(x, 1); /* n >= 2 */ P = gel(factoru(n), 1); l = lg(P)-1; s = P[1]; for (i = 2; i <= l; i++) s *= P[i]; q = n/s; if (tx == t_INT && is_pm1(x)) { avma = av; if (signe(x) > 0 || !odd(q)) return l == 1? utoipos(P[1]): gen_1; /* return Phi_s(-1) */ if (n == 2) return gen_0; if (!odd(n) && l == 2) return utoipos(P[2]); return gen_1; } if (q != 1) { x = gpowgs(x, q); n = s; } /* replace n by squarefree part */ if (tx == t_POL || tx == t_MAT || lg(x) > n) return gerepileupto(av, poleval(polcyclo(n,0), x)); xd = cgetg((1L< 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(talker,"precision<=0 in gprec"); 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(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(typeer,"binomial"); 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*bit_accuracy(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 >= 1, return bin, bin[k+1] = binomial(n, k) */ GEN vecbinome(long n) { long d = (n + 1)/2, k; GEN C = cgetg(n+2, t_VEC) + 1; /* C[k] = binomial(n, k) */ gel(C,0) = gen_1; gel(C,1) = utoipos(n); 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++) C[k] = 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 = diviiexact(mulii(t, muluu(n-m+k+1, n+k+1)), muluu(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 || m<0) pari_err(talker, "Negative arguments in stirling"); switch (flag) { case 1: return stirling1((ulong)n,(ulong)m); case 2: return stirling2((ulong)n,(ulong)m); default: pari_err(flagerr,"stirling"); } return NULL; /*NOT REACHED*/ } /***********************************************************************/ /** PERMUTATIONS **/ /***********************************************************************/ GEN numtoperm(long n, GEN x) { pari_sp av; ulong i, r; GEN v; if (n < 0) pari_err(talker,"n too small (%ld) in numtoperm",n); if (typ(x) != t_INT) pari_err(arither1); v = cgetg(n+1, t_VEC); v[1] = 1; av = avma; if (signe(x) <= 0) x = modii(x, mpfact(n)); for (r=2; r<=(ulong)n; r++) { ulong a; x = diviu_rem(x, r,&a); for (i=r; i>=a+2; i--) v[i] = v[i-1]; v[i] = r; if ((r & 0x1f) == 0) x = gerepileuptoint(av, x); } avma = av; for (i=1; i<=(ulong)n; i++) gel(v,i) = utoipos(v[i]); return v; } GEN permtonum(GEN x) { long lx=lg(x)-1, n=lx, last, ind, tx = typ(x); pari_sp av=avma; GEN ary,res; if (!is_vec_t(tx)) pari_err(talker,"not a vector in permtonum"); ary = cgetg(lx+1,t_VECSMALL); for (ind=1; ind<=lx; ind++) { res = gel(++x, 0); if (typ(res) != t_INT) pari_err(typeer,"permtonum"); ary[ind] = itos(res); } ary++; res = gen_0; for (last=lx; last>0; last--) { lx--; ind = lx; while (ind>0 && ary[ind] != last) ind--; res = addis(muliu(res,last), ind); while (ind++ < lx) ary[ind-1] = ary[ind]; } if (!signe(res)) res = mpfact(n); return gerepileuptoint(av, res); } /*******************************************************************/ /** **/ /** RECIPROCAL POLYNOMIAL **/ /** **/ /*******************************************************************/ /* return coefficients s.t x = x_0 X^n + ... + x_n */ GEN polrecip(GEN x) { if (typ(x) != t_POL) pari_err(typeer,"polrecip"); return RgX_recip(x); } /********************************************************************/ /** **/ /** POLYNOMIAL INTERPOLATION **/ /** **/ /********************************************************************/ /* 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 */ int no_dy = 1; if (!X) { X = cgetg(n+1, t_VEC); for (i=1; i<=n; i++) gel(X,i) = utoipos(i); X++; } switch(typ(x)) /* FIXME: should only be done if x,X,Y contain t_REALs */ case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: case t_QUAD: { GEN D = NULL; no_dy = 0; for (i=0; ib? 1: (ak); for (i=1; icmp(gel(x,v->k[i]), gel(y,v->k[i])); 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(typeer,"gen_sort"); *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(flagerr,"vecsort"); if (k) { long i, j, l, lk, tx, lx; GEN y; /* cf init_sort */ tx = typ(x); if (tx == t_LIST) { y = list_data(x); if (!y || (lx = lg(y)) == 1) return flag & cmp_IND? cgetg(1, t_VECSMALL): listcreate(); } else { if (!is_matvec_t(tx)) pari_err(typeer,"vecsort"); y = x; lx = lg(y); if (lx == 1) return flag & cmp_IND? cgetg(1, t_VECSMALL): cgetg(1, tx); } switch(typ(k)) { case t_INT: k = mkvecsmall(itos(k)); break; case t_VEC: case t_COL: k = ZV_to_zv(k); break; case t_VECSMALL: break; case t_CLOSURE: if (k[1] != 2) pari_err(talker,"comparison function needs exactly 2 arguments"); E = (void*)k; CMP = &closurecmp; goto END; default: pari_err(typeer,"vecsort"); } lk = lg(k); for (l=0,i=1; il) l = j; } for (j=1; j>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) { struct veccmp_s v; v.cmp = &gcmp; v.k = k; if (typ(k) != t_VECSMALL) pari_err(typeer,"vecsort"); return gen_indexsort(x, (void*)&v, &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) { struct veccmp_s v; v.cmp = &gcmp; v.k = k; if (typ(k) != t_VECSMALL) pari_err(typeer,"vecsort"); return gen_sort(x, (void*)&v, &veccmp); } 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); } /********************************************************************/ /** COMPARISON FUNCTIONS **/ /********************************************************************/ int cmp_nodata(void *data, GEN x, GEN y) { int (*cmp)(GEN,GEN)=(int (*)(GEN,GEN)) data; return cmp(x,y); } /* assume lg(x) = lg(y), x,y in Z^n */ int ZV_cmp(GEN x, GEN y) { long fl,i, lx = lg(x); for (i=1; i 0)? 1: -1) : ZV_cmp(gel(x,2), gel(y,2)); } int cmp_prime_ideal(GEN x, GEN y) { int k = cmpii(gel(x,1), gel(y,1)); 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 || typ(y) != t_VEC) pari_err(typeer,"setminus"); return gen_setminus(x,y,gcmp); } pari-2.5.5/src/basemath/random.c0000644000175000017500000001502512147140046015105 0ustar billbill/* $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. */ /********************************************************************/ /* */ /* 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(typeer, "setrand"); } 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 = bit_accuracy(prec); y = randomi(int2n(b)); if (!signe(y)) return real_0_bit(b); affir(y, x); setexpo(x, expo(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=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,"jbessel"); 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) { long i, lz, ki; pari_sp av = avma; GEN y; switch(typ(z)) { case t_INT: case t_FRAC: case t_QUAD: case t_REAL: case t_COMPLEX: { int flz0 = gequal0(z); long lim, k, precnew; GEN p1, p2; double B, L; i = precision(z); if (i) prec = i; if (flz0 && gequal0(n)) return real_1(prec); p2 = gdiv(gpow(gmul2n(z,-1),n,prec), ggamma(gaddgs(n,1),prec)); if (flz0) return gerepileupto(av, p2); L = 1.3591409 * gtodouble(gabs(gtofp(z,3),prec)); precnew = prec; if (L >= 1.0) precnew += 1 + (long)(L/(1.3591409*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 = bit_accuracy_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: y = cgetg_copy(z, &lz); for (i=1; i=0) l = linit; else l = linit - 1 + divsBIL(-2*k*gz); if (l>prec) prec = l; prec += divsBIL(-gz); if (prec < 3) prec = 3; z = gadd(z, real_0(prec)); if (typ(z) == t_COMPLEX) gel(z,2) = gadd(gel(z,2), real_0(prec)); p1 = gmul(_jbesselh(k,z,prec), gsqrt(gdiv(z,Pi2n(-1,prec)),prec)); avma = av; return affc_fixlg(p1, res); case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(z, &lz); for (i=1; i 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); setexpo(t, expo(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-bit_accuracy(precision(p1))) break; } swap(e, u); swap(f, v); affrr(mulrr(q,addrs(c,1)), q); if (expo(subrr(q,r)) - expo(r) <= 1-bit_accuracy(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); k = lg(Z)-2 - v; if (v < 0) pari_err(negexper,"_kbessel1"); 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; } static GEN kbesselintern(GEN n, GEN z, long flag, long prec) { long i, k, ki, lz, lim, precnew, fl, fl2, ex; pari_sp av = avma; GEN p1, p2, y, p3, pp, pm, s, c; double B, L; fl = (flag & 1) == 0; switch(typ(z)) { case t_INT: case t_FRAC: case t_QUAD: case t_REAL: case t_COMPLEX: if (gequal0(z)) pari_err(talker,"zero argument in a k/n bessel function"); 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 > bit_accuracy(prec)/16 + gexpo(n)) return kbessel1(n,z,prec); L = 1.3591409 * gtodouble(gabs(z,prec)); precnew = prec; if (L >= 1.3591409) { long rab = (long)(L/(1.3591409*LOG2*BITS_IN_LONG)); if (fl) rab *= 2; precnew += 1 + rab; } z = gtofp(z, precnew); if (issmall(n,&ki)) { GEN z2 = gmul2n(z, -1); k = labs(ki); B = bit_accuracy_mul(prec,LOG2/2) / L; if (fl) 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 (fl) { 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 = nbits2nlong(-ex); if (fl) 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 (fl) 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: y = cgetg_copy(z, &lz); for (i=1; i> 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(typeer,"kbesselintern"); 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)? lg(gx): prec, l1 = l+1; GEN y = ex? cgetc(l): cgetr(l); pari_sp av = avma; if(gsigne(gx) <= 0) pari_err(talker,"hyperu's third argument must be positive"); x = gtofp(gx, l); a1 = gaddsg(1, gadd(a,mb)); P = gmul(a1, a); p1 = gabs(gtofp(P,3), 3); n = (long)(bit_accuracy_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-bit_accuracy(precision(p1))) break; } swap(e, u); swap(f, v); affrr(mulrr(q, addrs(c,1)), q); if (expo(subrr(q,x)) - expo(x) <= 1-bit_accuracy(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; } /* = incgam2(0, x, prec). typ(x) = t_REAL. Optimized for eint1 */ static GEN incgam2_0(GEN x, GEN expx) { long l = lg(x), n, i; GEN z; if (expo(x) >= 4) { double mx = rtodbl(x), m = (bit_accuracy_mul(l,LOG2) + mx)/4; n = (long)(1+m*m/mx); 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) */ return divrr(addrr(real_1(l),z), mulrr(expx, x)); } else { GEN S, t, H, run = real_1(l+1); n = -bit_accuracy(l)-1; x = rtor(x, l+1); 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); } return subrr(mulrr(x, divrr(S,expx)), addrr(mplog(x), mpeuler(l))); } } /* assume x != 0 */ static GEN incgam2(GEN s, GEN x, long prec) { GEN b, x_s, S, y; long l, n, i; pari_sp av = avma, av2, avlim; double m,mx; if (typ(x) != t_REAL) x = gtofp(x, prec); if (gequal0(s) && typ(x) == t_REAL && signe(x) > 0) return gerepileuptoleaf(av, incgam2_0(x, mpexp(x))); if (typ(x) == t_COMPLEX) { double a = rtodbl(gel(x,1)); double b = rtodbl(gel(x,2)); l = precision(x); mx = sqrt(a*a + b*b); } else { l = lg(x); mx = fabs(rtodbl(x)); } m = (bit_accuracy_mul(l,LOG2) + mx)/4; n = (long)(1+m*m/mx); i = typ(s); if (i == t_REAL) b = addsr(-1,s); else { /* keep b integral : final powering more efficient */ GEN z = gtofp(s, prec); b = (i == t_INT)? addsi(-1,s): gaddsg(-1,z); s = z; } y = gmul(gexp(gneg(x), prec), gpow(x,b,prec)); x_s = gsub(x, s); av2 = avma; avlim = stack_lim(av2,3); S = gdiv(gaddsg(-n,s), gaddgs(x_s,n<<1)); for (i=n-1; i>=1; i--) { S = gdiv(gaddsg(-i,s), gadd(gaddgs(x_s,i<<1),gmulsg(i,S))); if (low_stack(avlim,stack_lim(av2,3))) { if(DEBUGMEM>1) pari_warn(warnmem,"incgam2"); 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 b, S, t, y; long l, n, i; 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 = -bit_accuracy(l)-1; i = typ(s); b = s; if (i != t_REAL) { s = gtofp(s, prec); if (i != t_INT) b = s; } av2 = avma; avlim = stack_lim(av2,3); S = t = real_1(l); for (i=1; 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); } } y = gdiv(gmul(gexp(gneg(x),prec), gpow(x,b,prec)), s); return gerepileupto(av, gmul(y,t)); } /* If g != NULL, assume that g=gamma(s,prec). */ GEN incgam0(GEN s, GEN x, GEN g, long prec) { pari_sp av; long es, e; GEN z; if (gequal0(x)) return g? gcopy(g): ggamma(s,prec); av = avma; es = gexpo(s); e = maxss(es, 0); if (gsigne(real_i(s)) <= 0 || gexpo(x) > e) z = incgam2(s,x,prec); else { if (es < 0) { long l = precision(s); if (!l) l = prec; prec = l + nbits2nlong(-es) + 1; s = gtofp(s, prec); x = gtofp(x, prec); } if (!g) g = ggamma(s,prec); z = gsub(g, incgamc(s,x,prec)); } return gerepileupto(av, z); } 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) { pari_sp av = avma; return gerepileuptoleaf(av, incgam2_0(x, expx)); } GEN eint1(GEN x, long prec) { long l, n, i; pari_sp av = avma; GEN p1, t, S, y; if (typ(x) != t_REAL) { x = gtofp(x, prec); if (typ(x) != t_REAL) pari_err(impl,"non-real argument in eint1"); } if (signe(x) >= 0) return gerepileuptoleaf(av, incgam2_0(x, mpexp(x))); /* rewritten from code contributed by Manfred Radimersky */ l = lg(x); n = bit_accuracy(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)); t = divru(p1, i); S = addrr(S, t); } y = addrr(S, addrr(mplog(y), mpeuler(l))); } else { p1 = invr(y); t = S = real_1(l); for (i = 1; expo(t) - expo(S) >= -n; i++) { t = mulrr(p1, mulru(t, i)); S = addrr(S, t); } y = mulrr(S, mulrr(p1, mpexp(y))); } return gerepileuptoleaf(av, negr(y)); } GEN veceint1(GEN C, GEN nmax, long prec) { if (!nmax) return eint1(C,prec); if (typ(nmax) != t_INT) pari_err(typeer,"veceint1"); if (typ(C) != t_REAL) { C = gtofp(C, prec); if (typ(C) != t_REAL) pari_err(typeer,"veceint1"); } if (signe(C) <= 0) pari_err(talker,"negative or zero constant in veceint1"); return mpveceint1(C, NULL, itos(nmax)); } /* C > 0 a t_REAL */ GEN mpveceint1(GEN C, GEN eC, long n) { long i, nstop, nmin, G, chkpoint, prec = lg(C); pari_sp av, av1; GEN y, e1, e2, F0, unr; if (n <= 0) return cgetg(1,t_VEC); y = cgetg(n+1,t_VEC); for(i=1; i<=n; i++) gel(y,i) = cgetr(prec); av = avma; G = expo(C); if (G >= 0) nstop = n; else { nstop = itos(ceilr(divur(4,C))); /* >= 4 ~ 4 / C */ if (nstop > n) nstop = n; } /* 1 <= nstop <= n */ if (!eC) eC = mpexp(C); if (DEBUGLEVEL>1) err_printf("veceint1: (n, nstop) = (%ld, %ld)\n",n, nstop); e1 = rcopy(eC); av1 = avma; affrr(incgam2_0(C, e1), gel(y,1)); for(i=2; i <= nstop; i++, avma = av1) { affrr(mulrr(e1, eC), e1); /* e1 = exp(iC) */ affrr(incgam2_0(mulur(i,C), e1), gel(y,i)); } if (nstop == n) { avma = av; return y; } e1 = powrs(eC, -n); e2 = powru(eC, 10); unr = real_1(prec); av1 = avma; G = -bit_accuracy(prec); F0 = gel(y,n); chkpoint = n; affrr(eint1(mulur(n,C),prec), F0); nmin = n; for(;;) { GEN minvn = divrs(unr,-n), My = subrr(minvn,C); GEN mcn = divrs(C, -n), Mx = mcn; GEN t = divrs(e1,-n), D = mkvec2( t, mulrr(My,t) ); long a, k, cD = 2; /* cD = #D */ /* D = [ e1/-n, (-1/n-C) * (e1/-n) ] */ nmin -= 10; if (nmin < nstop) nmin = nstop; My = addrr(My, minvn); if (DEBUGLEVEL>1 && n < chkpoint) { err_printf("%ld ",n) ; chkpoint -= nstop/20; } for (a=1,n--; n>=nmin; n--,a++) { GEN F = F0, den = stor(-a, prec); for (k=1;;) { GEN add; if (k > cD) { GEN z = addrr(mulrr(My, gel(D,cD)), mulrr(Mx,gel(D,cD-1))); Mx = addrr(Mx,mcn); My = addrr(My,minvn); D = shallowconcat(D, z); cD = k; /* My = -C - k/n, Mx = -C k/n */ } add = mulrr(den, gel(D,k)); if (expo(add) < G) { affrr(F,gel(y,n)); break; } F = addrr(F,add); k++; den = mulrs(divru(den, k), -a); /* den = prod(i=1,k, -a/i)*/ } } avma = av1; F0 = gel(y, ++n); if (n <= nstop) break; affrr(mulrr(e1,e2), e1); } if (DEBUGLEVEL>1) err_printf("\n"); avma = av; return y; } /* e t_REAL, vector of e^i, 1 <= i <= n */ GEN mpvecpow(GEN e, long n) { GEN G = cgetg(n+1, t_VEC); long j; 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 = bit_accuracy_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 = ceil((pow(rtodbl(gimag(x)),2)-pow(rtodbl(greal(x)),2))/(LOG2*BITS_IN_LONG)); 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+1), 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 ) */ 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 = bit_accuracy_mul(prec, LOG2); if (s <= 0) /* may occur if S ~ 0, and we don't use the func. eq. */ { /* TODO: the crude bounds below are generally valid. Optimize ? */ double l,l2, la = 1.; /* heuristic */ if (dnorm(s-1,t) < 0.1) /* |S - 1|^2 < 0.1 */ l2 = -(s - 0.5); else { 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; l2 = (p + s/2. - .25); n = 1 + dabs(l2, t/2) * la / PI; } else if (t != 0) { 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); if (beta <= 0) { if (s >= 1.0) { p = 0; n = exp((B - LOG2 + L) / s); } else { p = 1; n = dabs(s + 1, t) / (2*PI); } } else { beta = 1.0 - s + t * get_xinf(beta); if (beta > 0) { p = (long)ceil(beta / 2.0); n = dabs(s + 2*p-1, t) / (2*PI); } else { p = 0; n = exp((B - LOG2 + L) / s); } } } else { double sn = fabs(s); 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 + log(sn/s)) / s); } } *pp = p; *pn = (long)ceil(n); 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(bit_accuracy) we _really_ require */ GEN inv_szeta_euler(long n, double lba, long prec) { GEN z, res = cgetr(prec); pari_sp av = avma, avlim = stack_lim(av, 1); byteptr d = diffptr + 2; double A = n / (LOG2*BITS_IN_LONG), D; ulong p, lim; if (n > bit_accuracy(prec)) return real_1(prec); if (!lba) lba = bit_accuracy_mul(prec, LOG2); D = exp((lba - log(n-1)) / (n-1)); lim = 1 + (ulong)ceil(D); maxprime_check(lim); prec++; z = subir(gen_1, real2n(-n, prec)); for (p = 3; p <= lim;) { long l = prec + 1 - (long)floor(A * log(p)); 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); affrr(z, res); avma = av; } NEXT_PRIME_VIADIFF(p,d); } 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 + 1; GEN z; if (!iz) iz = inv_szeta_euler(n, 0., l); z = divrr(mpfactr(n, l), mulrr(powru(Pi2n(1, l), n), iz)); setexpo(z, expo(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 = divisors(utoipos( n/2 )); 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*itou(gel(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*BITS_IN_LONG); prec = (long)ceil(u); prec += 3; iz = inv_szeta_euler(n, t, prec); a = roundr( mulir(d, bernreal_using_zeta(n, iz, prec)) ); return gerepilecopy(av, mkfrac(a, d)); } /* y = binomial(n,k-2). Return binomial(n,k) */ static GEN next_bin(GEN y, long n, long k) { y = divru(mulru(y, n-k+2), k-1); return divru(mulru(y, n-k+1), k); } /* assume k > 1 odd */ static GEN szeta_odd(long k, long prec) { long kk, n, li = -(1+bit_accuracy(prec)); pari_sp av = avma, av2, limit; GEN y, p1, qn, z, q, pi2 = Pi2n(1, prec), binom= real_1(prec+1); q = mpexp(pi2); kk = k+1; /* >= 4 */ y = NULL; /* gcc -Wall */ 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); setlg(binom,prec+1); } p1 = mulrr(binom,p1); if (n == kk>>1) setexpo(p1, expo(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); qn = sqrr(q); z = invr( addrs(q,-1) ); for (n=2; ; n++) { long ep1, l; p1 = invr( mulir(powuu(n,k),addrs(qn,-1)) ); z = addrr(z,p1); if ((ep1 = expo(p1)) < li) break; l = (ep1 < 0) ? prec+1 : prec+1 + nbits2nlong(ep1); if (l < lg(qn)) setlg(qn, l); 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); } } setexpo(z, expo(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); qn = q; z=gen_0; for (n=1; ; n++) { long ep1, l; 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 ((ep1 = expo(p1)) < li) break; l = (ep1 < 0)? prec+1 : prec+1 + nbits2nlong(ep1); if (l < lg(qn)) setlg(qn, l); qn = mulrr(qn,q); if (low_stack(limit,stack_lim(av2,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"szeta, delta = %ld", ep1-li); gerepileall(av2,2, &z, &qn); } } setexpo(z, expo(z)+1); y = subrr(y,z); } return gerepileuptoleaf(av, y); } /* assume k > 0 even. Return B_k */ static GEN single_bern(long k, long prec) { GEN B; if (OK_bern(k >> 1, prec)) B = bernreal(k, prec); else if (k * (log(k) - 2.83) > bit_accuracy_mul(prec, LOG2)) B = bernreal_using_zeta(k, NULL, prec); else B = fractor(bernfrac(k), prec); 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(talker, "too large negative arg %ld in zeta", k); k = 1-k; y = single_bern(k, prec); togglesign(y); return gerepileuptoleaf(av, divru(y, k)); } if (k > bit_accuracy(prec)+1) return real_1(prec); if ((k&1) == 0) { if (!OK_bern(k >> 1, prec) && (k * (log(k) - 2.83) > bit_accuracy_mul(prec, LOG2))) y = invr( inv_szeta_euler(k, 0, prec) ); /* would use zeta above */ else { y = mulrr(powru(Pi2n(1, prec), k), single_bern(k, prec)); y = divrr(y, mpfactr(k,prec)); y[1] = evalsigne(1) | evalexpo(expo(y)-1); } return gerepileuptoleaf(av, y); } /* k > 1 odd */ if (k * log(k) > bit_accuracy_mul(prec, LOG2)) /* heuristic */ return gerepileuptoleaf(av, invr( inv_szeta_euler(k, 0, prec) )); return szeta_odd(k, prec); } /* return x^n, assume n > 0 */ static long pows(long x, long n) { long i, y = x; for (i=1; i 1 odd. tab[q] := q^-s, q prime power */ static GEN n_s(ulong n, GEN *tab) { byteptr d = diffptr + 2; GEN x = NULL; long p, e; for (p = 3; n > 1; ) { e = u_lvalrem(n, p, &n); if (e) { GEN y = tab[pows(p,e)]; if (!x) x = y; else x = gmul(x,y); } NEXT_PRIME_VIADIFF_CHECK(p,d); } 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, 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; byteptr d; pari_timer T; if (DEBUGLEVEL>2) timer_start(&T); s = trans_fix_arg(&prec,&s0,&sig,&av,&res); if (typ(s0) == t_INT) return gerepileupto(av, gzeta(s0, prec)); u = gsubgs(s, 1); /* temp */ if (gexpo(u) < -5 || (gexpo(s) > -5 && (signe(sig) <= 0 || expo(sig) < -1))) { /* s <--> 1-s */ GEN t; s = gneg(u); 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, bit_accuracy(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); maxprime_check((ulong)nn); 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); d = diffptr + 1; for (p=2; p < (ulong)nn;) { affur(p, rp); tab[p] = gexp(gmul(ms, mplog(rp)), prec); NEXT_PRIME_VIADIFF(p,d); } affsr(nn, rp); a = gexp(gmul(ms, mplog(rp)), prec); } sqn = (ulong)sqrt(nn-1.); d = diffptr + 2; /* fill in odd prime powers */ for (p=3; p <= sqn; ) { ulong oldq = p, q = p*p; while (q<(ulong)nn) { tab[q] = gmul(tab[p], tab[oldq]); oldq = q; q *= p; } NEXT_PRIME_VIADIFF(p,d); } 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; 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(talker, "argument must be a p-adic integer"); 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(talker, "argument equal to one in zeta"); 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); } return szeta(itos(x),prec); case t_REAL: case t_COMPLEX: return czeta(x,prec); case t_INTMOD: pari_err(typeer,"gzeta"); case t_PADIC: return zetap(x); case t_SER: pari_err(impl,"zeta of power series"); } return transc(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 = -(bit_accuracy(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(talker,"negative index in polylog"); 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+1); 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 = -bit_accuracy(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) ); setexpo(y, expo(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); } mpbern(m>>1, l); p1 = logabs(x); k = signe(p1); if (k > 0) { x = ginv(x); fl = !m2; } else fl = 0; /* |x| <= 1 */ if (k > 0) setsigne(p1, -1); setexpo(p1, expo(p1)+1); /* 2log|x| <= 0 */ y = polylog(m,x,l); y = m2? real_i(y): imag_i(y); if (m==1) y = gadd(y, gmul2n(p1,-2)); else { GEN p2 = gen_1; for (k=1; k>1)); else u = gneg_i(gmul2n(p2,-1)); /* u = p2*B_k */ 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, lx, 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: p1=cleanroots(gel(x,1),prec); lx=lg(p1); for (i=1; i=1; i--) a = gmul(y, gadd(a, powis(utoipos(i),-m))); return gerepileupto(av, a); case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i=1; i12) { 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 exp_Ir(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, exp_Ir(gmul(pi, x))); } } static GEN qq(GEN x, long prec) { long tx = typ(x); 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 (! ( x = toser_i(x)) ) pari_err(talker,"bad argument for modular function"); return x; } /* 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(talker,"non-positive valuation in eta"); 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(talker,"non-positive valuation in eta"); 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); if (is_scalar_t(tx)) l = -bit_accuracy(precision(q)); else { l = lg(q)-2; tx = 0; if (valp(q) <= 0) pari_err(talker,"non-positive valuation in eta"); } 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 (tx) { if (gexpo(ps)-gexpo(y) < l) return y; } else { if (valp(ps) >= 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 = gen_0, p = gen_1, pp = gen_0, s = gen_1; s2 = h = modii(h, k); while (signe(h)) { GEN r, nexth, a = dvmdii(k, h, &nexth); if (is_pm1(h)) s2 = addii(s2, mulii(p, s)); s1 = addii(s1, mulii(a, s)); togglesign_safe(&s); k = h; h = nexth; r = addii(mulii(a,p), pp); pp = p; p = r; } if (signe(s) < 0) s1 = subis(s1, 3); return gerepileupto(av, gdiv(addii(mulii(p,s1), s2), muliu(p,12))); } GEN sumdedekind(GEN h, GEN k) { pari_sp av = avma; GEN d; if (typ(h) != t_INT || typ(k) != t_INT) pari_err(typeer, "sumdedekind"); d = gcdii(h,k); if (!is_pm1(d)) avma = av; else { 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) >= -bit_accuracy(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(typeer,"trueeta"); 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 GEN jell(GEN x, long prec) { long tx = typ(x); pari_sp av = avma; GEN q, h, U; if (!is_scalar_t(tx) || tx == t_PADIC) { GEN p1, p2; q = qq(x,prec); p1 = gdiv(inteta(gsqr(q)), inteta(q)); p1 = gmul2n(gsqr(p1),1); p1 = gmul(q,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, raiѕed 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) ) < -bit_accuracy(prec) * <=> Im tau > bit_accuracy(prec) * log(2) / 2Pi */ long C = (long)bit_accuracy_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 = lg(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)); } /* sqrt(2) eta(2x) / eta(x) */ GEN weberf2(GEN x, long prec) { pari_sp av = avma; GEN z, t, a,b, Ua,Ub, s_a, s_b, 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); s_a = gel(st_a, 1); st_b = eta_correction(b, Ub, 1); s_b = gel(st_b, 1); t = gsub(gel(st_b,2), gel(st_a,2)); z = gmul(z, exp_IPiQ(t, prec)); if (s_b != gen_1) z = gmul(z, gsqrt(s_b, prec)); if (s_a != gen_1) z = gdiv(z, gsqrt(s_a, prec)); return gerepileupto(av, gmul(z, sqrtr(real2n(1, prec)))); } /* eta(x/2) / eta(x) */ GEN weberf1(GEN x, long prec) { pari_sp av = avma; GEN z, t, a,b, Ua,Ub, s_a, s_b, 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); s_a = gel(st_a, 1); st_b = eta_correction(b, Ub, 1); s_b = gel(st_b, 1); t = gsub(gel(st_b,2), gel(st_a,2)); z = gmul(z, exp_IPiQ(t, prec)); if (s_b != gen_1) z = gmul(z, gsqrt(s_b, prec)); if (s_a != gen_1) z = gdiv(z, gsqrt(s_a, prec)); return gerepileupto(av, z); } /* e(-1/24) * eta((x+1)/2) / eta(x) */ GEN weberf(GEN x, long prec) { pari_sp av = avma; GEN z, t, a,b, Ua,Ub, s_a, s_b, 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); s_a = gel(st_a, 1); st_b = eta_correction(b, Ub, 1); s_b = gel(st_b, 1); t = gsub(gsub(gel(st_b,2), gel(st_a,2)), mkfrac(gen_1, utoipos(24))); z = gmul(z, exp_IPiQ(t, prec)); if (s_b != gen_1) z = gmul(z, gsqrt(s_b, prec)); if (s_a != gen_1) z = gdiv(z, gsqrt(s_a, prec)); return gerepileupto(av, 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(flagerr,"weber"); } return NULL; /* not reached */ } 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 = gtofp(q, prec); if (gexpo(q) >= 0) pari_err(talker,"q >= 1 in theta"); 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 < -bit_accuracy(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(talker,"k < 0 in thetanullk"); l = precision(q); if (l) prec = l; q = gtofp(q, prec); if (gexpo(q) >= 0) pari_err(talker,"q >= 1 in theta"); 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) < -bit_accuracy(prec)) break; } p1 = gmul2n(gsqrt(gsqrt(q,prec),prec),1); if (k&2) y = gneg_i(y); return gerepileupto(av, gmul(p1, 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, n; pari_sp av = avma; GEN p1, ps, qn, y, ps2; l = precision(q); if (l) prec = l; q = gtofp(q, prec); if (gexpo(q) >= 0) pari_err(talker,"q >= 1 in theta"); qn = gen_1; ps2 = gsqr(q); ps = gneg_i(ps2); y = const_vec(k, gen_1); for (n = 3;; n += 2) { GEN t = NULL/*-Wall*/, P = utoipos(n), N2 = sqru(n); qn = gmul(qn,ps); ps = gmul(ps,ps2); 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_accuracy(prec)) break; } 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)); } pari-2.5.5/src/basemath/perm.c0000644000175000017500000006310012147140046014565 0ustar billbill/* $Id$ 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(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(typeer, "perm_to_GAP"); 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(talker,"empty group in group_domain"); 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 = const_vecsmall(n, 0); el = const_vecsmall(n, 0); 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(talker,"not a subgroup in group_subgroup_isnormal"); 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+2, t_VEC); k = 1; gel(s,k++) = strtoGENstr("PermutationGroup<"); gel(s,k++) = strtoGENstr( itostr( stoi(group_domain(G)) ) ); gel(s,k++) = strtoGENstr("|"); comma = strtoGENstr(", "); for (i = 1; i < l; ++i) { char *t = GENtostr( vecsmall_to_vec(gel(g,i)) ); if (i > 1) gel(s,k++) = comma; gel(s,k++) = strtoGENstr(t); pari_free(t); } 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(flagerr,"galoisexport"); return NULL; /*-Wall*/ } pari-2.5.5/src/basemath/Flx.c0000644000175000017500000020231112147140046014352 0ustar billbill/* $Id$ 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. */ #include "pari.h" #include "paripriv.h" /* Not so fast arithmetic with polynomials with small coefficients. */ /***********************************************************************/ /** **/ /** Flx **/ /** **/ /***********************************************************************/ /* Flx objects are defined as follows: Let l an ulong. An Flx is a t_VECSMALL: x[0] = codeword x[1] = evalvarn(variable number) (signe is not stored). x[2] = a_0 x[3] = a_1, etc. With 0 <= a_i < l signe(x) is not valid. Use degpol(x)>=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 vecsmall_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 */ 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); avma = av; ly = lx + v; x += lx; y = new_chunk(ly) + ly; /*cgetg could overwrite x!*/ 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)); } GEN Flx_sqrspec(GEN a, ulong p, long na) { GEN a0,c,c0,c1; 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 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); } } /* * x/polrecip(P)+O(x^n) */ static GEN Flx_invMontgomery_basecase(GEN T, ulong p) { long i, l=lg(T)-1, lr=l-1, k; GEN r=cgetg(lr,t_VECSMALL); r[1] = T[1]; r[2] = 1; if (SMALL_ULONG(p)) for (i=3;i=0; i--) if (x[i]) break; return i+1; } static GEN Flx_invMontgomery_Newton(GEN T, ulong p) { long nold, lx, lz, lq, l = degpol(T), lQ; GEN q, y, z, x = const_vecsmall(l+1, 0) + 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_invMontgomery(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_INVMONTGOMERY_LIMIT) { ulong c=T[l-1], ci=1; if (c!=1) { ci=Fl_inv(c,p); T=Flx_Fl_mul(T, ci, p); r=Flx_invMontgomery_basecase(T,p); r=Flx_Fl_mul(r,ci,p); } else r=Flx_invMontgomery_basecase(T,p); } else r = Flx_invMontgomery_Newton(T,p); return gerepileuptoleaf(ltop, r); } /* Compute x mod T where lg(x)<=2*lg(T)-2 * and mg is the Montgomery inverse of T. */ GEN Flx_rem_Montgomery(GEN x, GEN mg, GEN T, ulong p) { pari_sp ltop=avma; GEN z; long l = lgpol(x); long lt = degpol(T); /*We discard the leading term*/ long ld, lm, lT, lmg; if (l<=lt) return vecsmall_copy(x); (void)new_chunk(lt+2); ld = l-lt; lm = minss(ld, lgpol(mg)); lT = Flx_lgrenormalizespec(T+2,lt); lmg = Flx_lgrenormalizespec(mg+2,lm); z = Flx_recipspec(x+2+lt,ld,ld); /* z = rec(x) lz<=ld*/ z = Flx_mulspec(z+2,mg+2,p,lgpol(z),lmg); /* z = rec(x) * mg lz<=ld+lm*/ z = Flx_recipspec(z+2,minss(ld,lgpol(z)),ld);/* z = rec (rec(x) * mg) lz<=ld*/ z = Flx_mulspec(z+2,T+2,p,lgpol(z),lT); /* z *= pol lz<=ld+lt*/ avma=ltop; z = Flx_subspec(x+2,z+2,p,lt,minss(lt,lgpol(z)));/* z = x - z lz<=lt */ z[1]=x[1]; return z; } /* 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 vecsmall_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); } GEN Flx_rem(GEN x, GEN y, ulong p) { long dy = degpol(y), dx = degpol(x), d = dx-dy; if (d < 0) return Flx_copy(x); if (d+3 < Flx_REM_MONTGOMERY_LIMIT || d>dy-2) return Flx_rem_basecase(x,y,p); else { pari_sp av=avma; GEN mg = Flx_invMontgomery(y, p); return gerepileupto(av, Flx_rem_Montgomery(x, mg, y, p)); } } /* as FpX_divrem but working only on ulong types. * if relevant, *pr is the last object on stack */ GEN Flx_divrem(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(gdiver); if (pr == ONLY_REM) return Flx_rem(x, y, p); if (!dy) { if (pr && pr != ONLY_DIVIDES) *pr = pol0_Flx(sv); if (y[2] == 1UL) return vecsmall_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 = vecsmall_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; } 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))); } 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; } static GEN FlxM_mul2(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; } /* 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) { GEN m = cgetg(3, t_MAT); gel(m,1) = mkcol2(pol1_Flx(v),pol0_Flx(v)); gel(m,2) = mkcol2(pol0_Flx(v),pol1_Flx(v)); return m; } 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; if (degpol(y) lg(a)) swap(a, b); while (lgpol(b)) { GEN c = Flx_rem(a,b,p); 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 a; } GEN Flx_gcd(GEN x, GEN y, ulong p) { pari_sp av = avma, lim = stack_lim(av,2); if (!lgpol(x)) return vecsmall_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 gerepileupto(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 GEN Flx_extgcd_basecase(GEN a, GEN b, ulong p, 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_Flx(vx); v1 = pol1_Flx(vx); while (lgpol(d1)) { GEN r, q = Flx_divrem(d,d1,p, &r); v = Flx_sub(v,Flx_mul(q,v1,p),p); u=v; v=v1; v1=u; u=r; d=d1; d1=u; if (low_stack(lim,stack_lim(av,2))) { if (DEBUGMEM>1) 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,p2; 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) */ 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; i lg(z)) return z; return Flx_rem_Montgomery(z, mg, T, p); } /* Square of y in Z/pZ[X]/(T), as t_VECSMALL. */ static GEN Flxq_sqr_mg(GEN y,GEN mg,GEN T,ulong p) { GEN z = Flx_sqr(y,p); if (lg(T) > lg(z)) return z; return Flx_rem_Montgomery(z, mg, T, p); } typedef struct { GEN mg; GEN T; ulong p; } Flxq_muldata; static GEN _sqr_Montgomery(void *data, GEN x) { Flxq_muldata *D = (Flxq_muldata*)data; return Flxq_sqr_mg(x,D->mg, D->T, D->p); } static GEN _mul_Montgomery(void *data, GEN x, GEN y) { Flxq_muldata *D = (Flxq_muldata*)data; return Flxq_mul_mg(x,y,D->mg, D->T, D->p); } static GEN _Flxq_sqr(void *data, GEN x) { Flxq_muldata *D = (Flxq_muldata*)data; return Flxq_sqr(x, D->T, D->p); } static GEN _Flxq_mul(void *data, GEN x, GEN y) { Flxq_muldata *D = (Flxq_muldata*)data; return Flxq_mul(x,y, D->T, D->p); } /* 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; Flxq_muldata D; GEN y; long s = signe(n); if (!s) return pol1_Flx(T[1]); if (s < 0) x = Flxq_inv(x,T,p); if (is_pm1(n)) return s < 0 ? x : vecsmall_copy(x); D.T = T; D.p = p; if (lg(T) >= Flx_POW_MONTGOMERY_LIMIT) { D.mg = Flx_invMontgomery(T,p); y = gen_pow(x, n, (void*)&D, &_sqr_Montgomery, &_mul_Montgomery); } else y = gen_pow(x, n, (void*)&D, &_Flxq_sqr, &_Flxq_mul); return gerepileuptoleaf(av, y); } /* Inverse of x in Z/pZ[X]/(pol) or NULL if inverse doesn't exist * return lift(1 / (x mod (p,pol))) * not stack clean. * */ GEN Flxq_invsafe(GEN x, GEN T, ulong p) { GEN V, z = Flx_extgcd(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(gdiver); 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) { GEN mg=Flx_invMontgomery(T,p); GEN V = cgetg(l+2,t_VEC); long i, v = T[1]; gel(V,1) = pol1_Flx(v); if (l==0) return V; gel(V,2) = vecsmall_copy(x); if (l==1) return V; gel(V,3) = Flxq_sqr_mg(x,mg,T,p); if ((degpol(x)<<1) < degpol(T)) for(i = 4; i < l+2; i++) gel(V,i) = Flxq_mul_mg(gel(V,i-1),x,mg,T,p); else for(i = 4; i < l+2; i++) gel(V,i) = (i&1)? Flxq_sqr_mg(gel(V, (i+1)>>1),mg,T,p) : Flxq_mul_mg(gel(V, i-1),x,mg,T,p); return V; } 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); } /* assume T irreducible mod p */ int Flxq_issquare(GEN x, GEN T, ulong p) { pari_sp av; GEN m; ulong z; if (lg(x) == 2 || p == 2) return 1; av = avma; m = diviuexact(subis(powuu(p, degpol(T)), 1), p - 1); z = Flxq_pow(x, m, T, p)[2]; avma = av; return krouu(z, p) == 1; } static GEN _Flxq_pow(void *data, GEN x, GEN n) { Flxq_muldata *D = (Flxq_muldata*)data; return Flxq_pow(x,n, D->T, D->p); } static GEN _Flxq_rand(void *data) { pari_sp av=avma; Flxq_muldata *D = (Flxq_muldata*)data; GEN z; do { avma = av; z = random_Flx(degpol(D->T),D->T[1],D->p); } while (lgpol(z)==0); return z; } static ulong _Flxq_hash(GEN x) { ulong h = 0; long i, l=lgpol(x); for (i=0;i 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); 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; /* norm(g), assuming T is monic */ t = Flx_resultant(T, g, p); if (t == 1 || !is_gener_Fl(t, p, p_1, L)) continue; tt = Flxq_pow(g, utoi(p_1>>1), T, p); } RES = p_1; for (i = 1; i < j; i++) { GEN a = Flxq_pow(tt, gel(L2,i), T, p); if (!degpol(a) && (ulong)a[2] == RES) break; } if (i == j) break; } if (!po) g = gerepilecopy(av0, g); else { *po = mkvec2(subis(powuu(p,f), 1), o); gerepileall(av0, 2, &g, po); } return g; } /***********************************************************************/ /** **/ /** 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; } /*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 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; jlx) 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_invMontgomery_basecase(GEN T, GEN Q, ulong p) { long i, l=lg(T)-1, k; long sv=Q[1]; GEN r=cgetg(l,t_POL); r[1]=T[1]; gel(r,2) = pol0_Flx(sv); gel(r,3) = pol1_Flx(sv); for (i=4;i=0; i--) if (!lgpol(gel(x,i))) break; return i+1; } static GEN FlxqX_invMontgomery_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; ulong mask = quadratic_prec_mask(l-2); /* assume l > 2 */ for (i=0;i1 && signe(gel(q,1))) { GEN u = gel(q, 1); if (!equali1(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 (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 = 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] = T[1]; return gerepilecopy(av, x); } static const long FlxqX_INVMONTGOMERY_LIMIT = 5; /* x/polrecip(P)+O(x^n) */ GEN FlxqX_invMontgomery(GEN T, GEN Q, ulong p) { pari_sp ltop=avma; long l=lg(T); GEN r; GEN c=gel(T,l-1), ci=NULL; if (l<5) return pol0_Flx(T[1]); if (l<=FlxqX_INVMONTGOMERY_LIMIT) { if (!Flx_equal1(c)) { ci= Flxq_inv(c,Q,p); T = FlxqX_Flxq_mul(T, ci, Q, p); r = FlxqX_invMontgomery_basecase(T,Q,p); r = FlxqX_Flxq_mul(r,ci,Q,p); } else r = FlxqX_invMontgomery_basecase(T,Q,p); } else r = FlxqX_invMontgomery_Newton(T,Q,p); return gerepileupto(ltop, r); } GEN FlxqX_rem_Montgomery(GEN x, GEN mg, GEN T, GEN Q, ulong p) { pari_sp ltop=avma; GEN z; long vs=Q[1]; 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 */ z[1]=T[1]; 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 vecsmall_copy(Q); if (!signe(Q)) return vecsmall_copy(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,T[1]); 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); } 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; GEN W = cgetg(lg(V),t_VEC); for(k=1; k < lg(V); k++) gel(W,k) = deg1pol_shallow(pol1_Flx(T[1]),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(gdiver); return gerepileupto(av, U); } typedef struct { GEN T, S; ulong p; } FlxqXQ_muldata; static GEN _FlxqXQ_mul(void *data, GEN x, GEN y) { FlxqXQ_muldata *d = (FlxqXQ_muldata*) data; return FlxqXQ_mul(x,y, d->S,d->T, d->p); } static GEN _FlxqXQ_sqr(void *data, GEN x) { FlxqXQ_muldata *d = (FlxqXQ_muldata*) data; return FlxqXQ_sqr(x, d->S,d->T, d->p); } /* 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),T[1]); if (s < 0) x = FlxqXQ_inv(x,S,T,p); if (is_pm1(n)) return s < 0 ? x : gcopy(x); D.S = S; D.T = T; D.p = p; return gen_pow(x, n, (void*)&D, &_FlxqXQ_sqr, &_FlxqXQ_mul); } /*******************************************************************/ /* */ /* FlxYqQ */ /* */ /*******************************************************************/ /*Preliminary implementation to speed up FpX_ffisom*/ typedef struct { GEN S, T, mg; 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 mg, GEN T, ulong p) { pari_sp ltop=avma; long n=degpol(S); long m=degpol(T); long w = S[1]; GEN V = FlxX_swap(x,n,w); (void) mg; /*TODO really use mg*/ V = FlxqX_red(V,T,p); V = FlxX_swap(V,m,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->S, D->p),D->S,D->mg,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->S, D->p),D->S,D->mg,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.5.5/src/basemath/lll.c0000644000175000017500000006233212147140046014413 0ustar billbill/* $Id$ 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/ */ /* x - s*y */ static GEN submulu(GEN x, GEN y, ulong s) { pari_sp av; if (!signe(y)) return x; av = avma; (void)new_chunk(3+lgefint(x)+lgefint(y)); /* HACK */ y = mului(s,y); avma = av; return subii(x, y); } static GEN addmulu(GEN x, GEN y, ulong s) { pari_sp av; if (!signe(y)) return x; av = avma; (void)new_chunk(3+lgefint(x)+lgefint(y)); /* HACK */ y = mului(s,y); avma = av; return addii(x, y); } static GEN submul(GEN x, GEN y, GEN s) { pari_sp av; if (!signe(y)) return x; av = avma; (void)new_chunk(lgefint(s)+lgefint(x)+lgefint(y)); /* HACK */ y = mulii(s,y); avma = av; return subii(x, y); } /***********************************************/ /* 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 = lg(gel(B,1))-1; } 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>=4 && 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 = 3; ; 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 prec) prec = l; } return prec; } long ZM_max_lg(GEN x) { long i, prec = 2, n = lg(x); if (n != 1) { long j, m = lg(x[1]); 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 = lg(x[1]); for (j=1; j 0) s = c; } } return absi(s); } /********************************************************************/ /** **/ /** MULTIPLICATION **/ /** **/ /********************************************************************/ /* x non-empty ZM, y a compatible zc (dimension > 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 = lg(x[1]); for (j = 1; j < ly; j++) gel(z,j) = ZM_zc_mul_i(x, gel(y,j), l,c); return z; } /* x[i,]*y. Assume lg(x) > 1 and 0 < i < lg(x[1]) */ 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 = lg(x[1]) */ 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 < l; i++) gel(z,i) = ZMrow_ZC_mul_i(x, y, i, lx); return z; } GEN ZM_mul(GEN x, GEN y) { long j, l, lx=lg(x), ly=lg(y); GEN z; if (ly==1) return cgetg(1,t_MAT); /* if (lx != lg(y[1])) pari_err(operi,"*",x,y); */ if (lx==1) return zeromat(0, ly-1); l = lg(x[1]); z = cgetg(ly,t_MAT); for (j=1; j 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); } GEN ZV_ZM_mul(GEN x, GEN y) { long i, lx = lg(x), ly = lg(y); GEN z; if (lx == 1) return zerovec(ly-1); z = cgetg(ly, t_VEC); for (i = 1; i < ly; i++) gel(z,i) = ZV_dotproduct_i(x, gel(y,i), lx); return z; } GEN ZC_ZV_mul(GEN x, GEN y) { long i,j, lx=lg(x), ly=lg(y); GEN z; if (ly==1) return cgetg(1,t_MAT); z = cgetg(ly,t_MAT); for (j=1; j < ly; j++) { gel(z,j) = cgetg(lx,t_COL); for (i=1; i 0)? ZC_copy(X): ZC_neg(X); l = lg(X); A = cgetg(l, t_COL); for (i=1; i 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 */ if (m == 3) { long s = signe(v); ulong w = v[2]; if (w == 1) /* v = +- 1 */ { if (s > 0) { /* 1 */ for (i = lg(X)-1; i; i--) if (signe(Y[i])) gel(X,i) = addii(gel(X,i), gel(Y,i)); } else { /* -1 */ for (i = lg(X)-1; i; i--) if (signe(Y[i])) gel(X,i) = subii(gel(X,i), gel(Y,i)); } return; } for (i = lg(X)-1; i; i--) { GEN p1 = gel(X,i), p2 = gel(Y,i); if (!signe(p1)) { gel(X,i) = mului(w,p2); if (s < 0) togglesign(gel(X,i)); } else if (signe(p2)) { pari_sp av = avma; (void)new_chunk(1+lgefint(p1)+lgefint(p2));/*HACK*/ p2 = mului(w,p2); if (s < 0) togglesign(p2); avma = av; gel(X,i) = addii(p1,p2); } } return; } /* m > 3 */ for (i = lg(X)-1; i; i--) { GEN p1 = gel(X,i), p2 = gel(Y,i); if (!signe(p1)) gel(X,i) = mulii(v,p2); else if (signe(p2)) { pari_sp av = avma; (void)new_chunk(m+lgefint(p1)+lgefint(p2)); /*HACK*/ p2 = mulii(v,p2); avma = av; gel(X,i) = addii(p1,p2); } } } /* X + v Y */ static GEN ZC_lincomb1(GEN v, GEN X, GEN Y) { long i, lx = lg(X), m = lgefint(v); GEN p1, p2, A = cgetg(lx,t_COL); if (is_bigint(v)) { 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 */ lx = lg(X); A = cgetg(lx,t_COL); m = lgefint(u)+lgefint(v); 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 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)); } /********************************************************************/ /** **/ /** "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_hnfremdiv(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(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 = lg(A[1]); if (lg(B[1]) != 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 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 != lg(x[1])) return 0; for (j=1; j 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.5.5/src/basemath/bb_group.c0000644000175000017500000004026512147140046015430 0ustar billbill/* $Id$ 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<> r) & 1; } /* assume n != 0, t_INT. Compute x^|n| using sliding window powering */ static GEN sliding_window_powu(GEN x, ulong n, long e, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)) { pari_sp ltop = avma, av, lim; long i, l = expu(n), u = (1UL<<(e-1)); long w, v; GEN tab = cgetg(1+u, t_VEC); GEN x2 = sqr(E, x), z = NULL, tw; gel(tab, 1) = x; for (i=2; i<=u; i++) gel(tab,i) = mul(E, gel(tab,i-1), x2); av = avma; lim = stack_lim(av, 1); while (l>=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"); 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"); z = gerepilecopy(av, z); } if (int_bit(n,l)) break; z = sqr(E, z); l--; } } return gerepilecopy(ltop, z); } /* assume n != 0, t_INT. Compute x^|n| using leftright binary powering */ static GEN leftright_binary_powu(GEN x, long n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)) { pari_sp av = avma, lim = stack_lim(av, 1); GEN y = x; long m = (long) n, j = 1+bfffo(m); /* normalize, i.e set highest bit to 1 (we know m != 0) */ m<<=j; j = BITS_IN_LONG-j; /* first bit is now implicit */ for (; j; m<<=1,j--) { y = sqr(E,y); if (m < 0) 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"); y = gerepilecopy(av, y); } } return gerepilecopy(av, y); } GEN gen_powu(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); if (l<=24) return sliding_window_powu(x, n, 2, E, sqr, mul); return sliding_window_powu(x, n, 3, E, sqr, mul); } GEN gen_pow(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)) { long l; if (lgefint(n)==3) return gen_powu(x,(ulong)n[2],E,sqr,mul); l = expi(n); if (l<=64) return sliding_window_pow(x, n, 3, E, sqr, mul); if (l<=160) return sliding_window_pow(x, n, 4, E, sqr, mul); if (l<=384) return sliding_window_pow(x, n, 5, E, sqr, mul); if (l<=896) return sliding_window_pow(x, n, 6, E, sqr, mul); return sliding_window_pow(x, n, 7, E, sqr, mul); } /***********************************************************************/ /** **/ /** 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(grp->pow(E,g,gen_0),gen_0,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->cmp(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,smalltable,giant,perm,v,g0inv; p1 = sqrti(q); if (cmpiu(p1,LGBITS) >= 0) pari_err(talker,"order too large in gen_Shanks_log"); lbaby = itos(p1)+1; smalltable = cgetg(lbaby+1,t_VEC); g0inv = grp->pow(E,g0,gen_m1); for (p1=x, i=1;;i++) { av1 = avma; if (grp->equal1(p1)) { avma = av; return stoi(i-1); } gel(smalltable,i) = p1; if (i==lbaby) break; p1 = gerepileupto(av1, grp->mul(E,p1,g0inv)); } p1 = giant = grp->mul(E,x,grp->pow(E, p1, gen_m1)); gen_sort_inplace(smalltable, (void*)grp->cmp, &cmp_nodata, &perm); av1 = avma; lim=stack_lim(av1,2); for (k=1; k<= lbaby; k++) { i=tablesearch(smalltable,p1,grp->cmp); if (i) { v=addis(mulss(lbaby-1,k),perm[i]); return gerepileuptoint(av,addsi(-1,v)); } p1 = grp->mul(E,p1,giant); if (low_stack(lim, stack_lim(av1,2))) { if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_log, k = %ld", k); p1 = gerepileupto(av1, p1); } } pari_err(talker,"gen_Shanks_log: supplied order (= %Ps) is incorrect", q); return NULL; /* not reached */ } /*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, GEN easy(void*E, GEN, GEN, GEN)) { if (easy) { GEN e = easy(E, x, g, p); if (e) return e; } if (grp->equal1(x)) return gen_0; if (!grp->cmp(x,g)) return gen_1; if (grp->hash==NULL || 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_factor(o)) return mkvec2(factorback(o), o); break; case t_VEC: if (lg(o) == 3 && signe(gel(o,1)) > 0 && is_Z_factor(gel(o,2))) return o; break; } pari_err(typeer, "generic discrete logarithm (order factorization)"); 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(typeer, "generic discrete logarithm (order factorization)"); return NULL; /* not reached */ } /* easy() 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, GEN easy(void *E, GEN, GEN, GEN)) { 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->cmp(g, a)==0) return gen_1; /* frequent special case */ if (easy) { GEN e = easy(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 */ g_q = grp->pow(E,g, mulii(t0, gel(qj,e-1))); /* order q */ n_q = gen_0; for (j=0;; j++) { /* n_q = sum_{ipow(E,a0, gel(qj,e-1-j)); b = gen_plog(b, g_q, q, E, grp, easy); n_q = addii(n_q, mulii(b, gel(qj,j))); if (j == e-1) 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)); } return gerepileuptoint(av, lift(chinese1_coprime_Z(v))); } /***********************************************************************/ /** **/ /** ORDER OF AN ELEMENT **/ /** **/ /***********************************************************************/ /*Find the exact order of a assuming a^o==1*/ GEN gen_eltorder(GEN a, GEN o, void *E, const struct bb_group *grp) { pari_sp av = avma; long i; GEN m; m = dlog_get_ordfa(o); if (!m) pari_err(talker,"missing order in gen_eltorder"); o = gel(m,1); m = gel(m,2); for (i = lg(m[1])-1; i; i--) { GEN t, y, p = gcoeff(m,i,1); long j, e = itos(gcoeff(m,i,2)); 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); } /*******************************************************************/ /* */ /* n-th ROOT */ /* */ /*******************************************************************/ /* Assume l is prime. Return a non l-th power 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; } /* 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, GEN q,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,a,Fp_mul(negi(u1),r,q)); 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 = negi(gen_plog(z,m,l,E,grp,NULL)); p1 = grp->pow(E,y, Fp_mul(dl,powiu(l,e-k-1),q)); 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 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 = lg(F[1])-1; 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,q,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; } pari-2.5.5/src/basemath/base3.c0000644000175000017500000015566512147140046014641 0ustar billbill/* $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. */ /*******************************************************************/ /* */ /* 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 = lg(tab[1])-1; 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++) m[k] = 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): gneg(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; } GEN tablemulvec(GEN M, GEN x, GEN v) { long l, i; GEN y, dx = NULL; if (RgV_isscalar(x)) return RgV_Rg_mul(v, gel(x,1)); x = multable(M, x); l = lg(v); y = cgetg(l, t_VEC); for (i=1; i < l; i++) { GEN c = gel(v,i); if (typ(c)!=t_COL) c = RgC_Rg_mul(gel(x,1), c); else c = RgM_RgC_mul(x,c); gel(y,i) = c; } return dx? gdiv(y, dx): 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(talker,"not an integer exponent in nfpow"); 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) = powiu(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(talker,"not an integer exponent in nfpow"); nf = checknf(nf); N = nf_get_degree(nf); s = signe(n); if (s < 0) pari_err(talker,"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 = leftright_pow_fold(col_ei(N, I), n, (void*)&D, &sqr_mod, &ei_msqr_mod); return gerepileupto(av,y); } /* valuation of integer x, with resp. to prime ideal P above p. * p.P^(-1) = b Z_K * [b may be given as the 'multiplication by b' matrix, possibly a t_INT] */ long int_elt_val(GEN nf, GEN x, GEN p, GEN b, GEN *newx) { long i, k, w, N; GEN r, a, y, mul = zk_scalar_or_multable(nf, b); if (typ(mul) == t_INT) return newx? ZV_pvalrem(x, p, newx):ZV_pval(x, p); N = nf_get_degree(nf); y = cgetg(N+1, t_COL); /* will hold the new x */ x = leafcopy(x); for(w=0;; w++) { for (i=1; i<=N; i++) { /* compute (x.b)_i */ a = mulii(gel(x,1), gcoeff(mul,i,1)); for (k=2; k<=N; k++) a = addii(a, mulii(gel(x,k), gcoeff(mul,i,k))); /* is it divisible by p ? */ gel(y,i) = dvmdii(a,p,&r); if (r != gen_0) { if (newx) *newx = x; return w; } } swap(x, y); } } 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 = int_elt_val(nf,x,p, pr_get_tau(pr), NULL); if (cx) w += e*Q_pval(cx,p); avma = av; 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: if (!RgX_equal_var(nf_get_pol(nf),gel(x,1))) pari_err(talker,"not the same number field in basistoalg"); return gcopy(x); case t_POL: T = nf_get_pol(nf); if (varn(T) != varn(x)) pari_err(consister,"basistoalg"); z = cgetg(3,t_POLMOD); gel(z,1) = gcopy(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) = gcopy(T); gel(z,2) = gcopy(x); return z; default: pari_err(typeer,"basistoalg"); 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(talker,"incompatible variables in nf_to_scalar_or_basis"); 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(typeer,"nf_to_scalar_or_basis"); 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(typeer,"nf_to_scalar_or_alg"); return NULL; /* not reached */ } /* gmul(A, RgX_to_RgV(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(lg(A[1])-1); 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(talker,"not the same number field in algtobasis"); 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: return gcopy(x); case t_INT: case t_FRAC: return scalarcol(x, nf_get_degree(nf)); } pari_err(typeer,"algtobasis"); return NULL; /* not reached */ } GEN rnfbasistoalg(GEN rnf,GEN x) { long lx, i; pari_sp av = avma; GEN z, nf; checkrnf(rnf); switch(typ(x)) { case t_VEC: case t_COL: z = cgetg_copy(x, &lx); nf = gel(rnf,10); for (i=1; i> 0 at sarch */ GEN set_sign_mod_divisor(GEN nf, GEN x, GEN y, GEN divisor, GEN sarch) { GEN s, archp, gen; long nba,i; if (!sarch) return y; gen = gel(sarch,2); nba = lg(gen); if (nba == 1) return y; archp = vec01_to_indices(gel(divisor,2)); s = nfsign_arch(nf, y, archp); if (x) Flv_add_inplace(s, nfsign_arch(nf, x, archp), 2); s = Flm_Flc_mul(gel(sarch,3), s, 2); 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 = scalarcol_shallow(pgener_Fp(p), nf_get_degree(nf)); 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)^* */ prh = idealhnf_two(nf,pr); pre = (e==1)? prh: idealpow(nf,pr,ep); g0 = g; u = v = NULL; /* gcc -Wall */ if (x) { GEN uv = idealaddtoone(nf,pre, idealdivpowprime(nf,x,pr,ep)); u = gel(uv,1); v = zk_scalar_or_multable(nf, gel(uv,2)); g0 = makeprimetoideal(x,u,v,g); } list = vectrunc_init(e+1); y = mkvec5(mkvec(addis(powiu(p,f), -1)), mkvec(g), mkvec(g0), mkvec(nfsign_arch(nf,g0,arch)), gen_1); vectrunc_append(list, y); prb = prh; for (a = b = 1; a < e; a = b) { GEN pra = prb, gen, z, s, U; long i, l; b <<= 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); if(DEBUGLEVEL>3) err_printf("zidealij done\n"); 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); } 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 = lg(v[1]) - 1; 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++) mat[i] = 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 (lg(bas[1]) > 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); } /* 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) { GEN L, e, cyc, gen, s, U; long i,j, llist = lg(list)-1; for (j = 1; j <= llist; j++) { L = gel(list,j); 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 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 */ } /* here lg(e) == lg(cyc) */ for (i = 1; i < lg(cyc); i++) { GEN t; if (typ(gel(e,i)) != t_INT) pari_err(talker,"%Ps not coprime to %Ps in 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); return mkmat( 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 = const_vecsmall(narchp,0); /*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; i3 && 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, uv = idealaddtoone(nf,gel(f1,1),gel(f2,1)); u = gel(uv,1); v = gel(uv,2); mv = zk_scalar_or_multable(nf, v); if (typ(mv) == t_INT) mu = subsi(1,mv); else mu = RgM_Rg_add(ZM_neg(mv), gen_1); /* mult by u = 1-v */ gen = shallowconcat(makeprimetoidealvec(x,u,mv, gel(G1,3)), makeprimetoidealvec(x,v,mu, gel(G2,3))); } y = cgetg(6,t_VEC); gel(y,1) = mkvec2(x, gel(f1,2)); 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); return Flm_Flc_mul(gmael(lists, lg(lists)-1, 3), rowpermute(sgnU, vec01_to_indices(arch)), 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; byteptr ptdif = diffptr; pari_sp lim, av, av0 = avma; long i, j, l; GEN nf, z, p, fa, id, U, empty = cgetg(1,t_VEC); 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); av = avma; lim = stack_lim(av,1); maxprime_check(bound); for (p[2] = 0; (ulong)p[2] <= bound; ) { NEXT_PRIME_VIADIFF(p[2], ptdif); 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 */ { 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(flagerr,"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; long i, lx1; GEN f1, G1, fa1, lists1, 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); lists1 = gel(bid1,4); lx1 = lg(lists1); lists = cgetg(lx1,t_VEC); for (i=1; i3)? 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, 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(typeer, "ideallistarch"); if (l == 1) return cgetg(1,t_VEC); z = gel(L,1); if (typ(z) != t_VEC) pari_err(typeer, "ideallistarch"); 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(typeer,"ideallistarch"); 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= 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); } /*******************************************************************/ /* 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, ax, bo, sol, mod = NULL; long vP = varn(P), vT = varn(T), dT = degpol(T), dM = 0, dR; ulong p; byteptr primepointer; 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))); btop = avma; st_lim = stack_lim(btop, 1); primepointer = init_modular(&p); for (;;) { NEXT_PRIME_VIADIFF_CHECK(p, primepointer); /*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 = RgXX_to_RgM(FlxX_to_ZXX(R), dT); /* previous primes divided Res(P/gcd, Q/gcd)? Discard them. */ if (!mod || dR < dM) { M = R; 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); } ax = muliu(Fp_inv(utoipos(p), mod), p); M = ZM_add(R, ZM_Z_mul(ZM_sub(M, R), ax)); mod = muliu(mod, p); M = FpM_red(M, mod); /* 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(typeer,"nffactormod"); if (varncmp(vx,vn) >= 0) pari_err(talker,"polynomial variable must have highest priority in nffactormod"); 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 (paranoia) */ if (typ(P0) == t_POL) P0 = gel(P0,2); /* non-0 constant */ 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 get_den(GEN *pnf, GEN T) { GEN den = gen_1; if (!*pnf) { GEN fa, P, q, D; *pnf = nfinitall(T, nf_PARTIALFACT, DEFAULTPREC); D = nf_get_disc(proper_nf(*pnf)); if (is_pm1(D)) return gen_1; fa = Z_factor_limit(D, 0); P = gel(fa,1); q = gel(P, lg(P)-1); if (!BPSW_psp(q)) den = q; /* nf_get_disc(nf) may be incorrect */ } return den; } /* set B = A/gcd(A,A'), squarefree */ static GEN get_nfsqff_data(GEN *pnf, GEN *pT, GEN *pA, GEN *pB, GEN *ptbad) { GEN den, bad, A = *pA, T = *pT; long n = degpol(T); if (nfsqff_use_Trager(n, degpol(A))) { *pnf = T; bad = den = ZX_disc(T); if (is_pm1(leading_term(T))) den = indexpartial(T, den); } else { GEN nf; den = get_den(pnf, T); nf = proper_nf(*pnf); bad = nf_get_index(nf); if (den != gen_1) bad = mulii(bad, den); if (nf != *pnf) { /* t_POL defining base field changed (not monic) */ long i, l; GEN a = cgetg_copy(A, &l); GEN rev = gel(*pnf,2), pow, dpow; *pT = T = nf_get_pol(nf); /* need to update T */ pow = QXQ_powers(lift_intern(rev), n-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]; t = gel(pol,l-1); gel(x,l-1) = mul_content(T->L->topowden, t); 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) */ pari_sp av1 = avma; long j; GEN quo, p, r, Bp, lb = leading_term(B), E = cgetalloc(t_VECSMALL,n+1); byteptr pt = diffptr; ulong pp = 0; for (;; avma = av1) { NEXT_PRIME_VIADIFF_CHECK(pp, pt); 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 = rnf_fix_pol(T,pol,1); dA = degpol(A); if (dA <= 0) { avma = (pari_sp)(rep + 3); return (dA == 0)? trivfact(): 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 */ static GEN arch_for_T2(GEN G, GEN x) { return (typ(x) == t_COL)? gmul(G,x): gmul(gel(G,1),x); } static GEN arch_for_T2_prec(GEN G, GEN x, long prec) { return (typ(x) == t_COL)? gmul(G, RgC_gtofp(x,prec)) : gmul(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 (!gequal1(lS)) binlS = gmul(lS, bin); 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 */ { gel(N2,j) = sqrtr( RgC_fpnorml2(gel(matGS,j), DEFAULTPREC) ); if (lg(N2[j]) < DEFAULTPREC) goto PRECPB; } for ( ; j <= n; j+=2) { GEN q1 = RgC_fpnorml2(gel(matGS,j ), DEFAULTPREC); GEN q2 = RgC_fpnorml2(gel(matGS,j+1), DEFAULTPREC); p1 = gmul2n(addrr(q1, q2), -1); gel(N2,j) = gel(N2,j+1) = sqrtr(p1); if (lg(N2[j]) < DEFAULTPREC) goto PRECPB; } if (j > n) break; /* done */ PRECPB: prec = (prec<<1)-2; 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_sigma | binom(d-1, i-1) ||sigma(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 = 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 i,prec,precnf, d = degpol(polbase), n = nf_get_degree(nf); precnf = gprecision(G); prec = MEDDEFAULTPREC; bin = vecbinome(d); POL = polbase + 2; /* compute [POL]_2 */ for (;;) { s = real_0(prec); for (i=0; i<=d; i++) { GEN p1 = gnorml2(arch_for_T2_prec(G, gel(POL,i), prec)); if (!signe(p1)) continue; if (lg(p1) == 3) break; /* s += T2(POL[i]) / binomial(d,i) */ s = addrr(s, gdiv(p1, gel(bin,i+1))); } if (i > d) break; prec = (prec<<1)-2; if (prec > precnf) { nffp_t F; 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 = ZXY_max_lg(P) + 1; l = lg(P); if (nf && nf_get_prec(nf) >= prec) R = nf_get_roots(nf); else R = cleanroots(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 = lg(T->dPinvS[1]); 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; T->S1[k] = T->S1[i]; T->dPinvS[k] = 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, C2lt, C2ltpol; } div_data; static void init_div_data(div_data *D, GEN pol, GEN C) { GEN C2lt, lc = leading_term(pol), lt = is_pm1(lc)? NULL: absi(lc); if (C) { GEN C2 = sqri(C); C2lt = lt ? mulii(C2, lt): C2; } else C2lt = lt; D->lt = lt; D->C = C; D->C2lt = C2lt; D->C2ltpol = C2lt? RgX_Rg_mul(pol, C2lt): pol; } static void update_target(div_data *D, GEN pol) { D->C2ltpol = D->C? RgX_Rg_mul(pol, D->C): 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 pol = T->pol, nf = T->nf, famod = T->fact, dn = T->dn, bound = T->bound; GEN lt, 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_COL); 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, pol, T->L->topowden); ltdn = mul_content(D.lt, dn); lt = D.lt; /* to be restored at the end */ { GEN q = ceil_safe(sqrtr(T->BS_2)); GEN t1,t2, lt2dn; GEN trace1 = cgetg(lfamod+1, t_MAT); GEN trace2 = cgetg(lfamod+1, t_MAT); lt2dn= mul_content(ltdn, D.lt); 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; /* d - 1 test */ if (T1) { t = get_trace(ind, T1); if (rtodbl(RgC_fpnorml2(t,DEFAULTPREC)) > Bhigh) { if (DEBUGLEVEL>6) err_printf("."); avma = av; goto NEXT; } } /* d - 2 test */ if (T2) { 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 = C*lt*\prod_{i in ind} famod[i] */ y = nf_pol_lift(y, bound, T); if (!y) { if (DEBUGLEVEL>3) err_printf("@"); avma = av; goto NEXT; } /* y is apparently in O_K[X], in fact in (Z[Y]/nf.pol)[X] due to the * multiplication by C. 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; } /* 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]), a * K-rational factor, in fact in Z[Y]/nf.pol)[X] as above. */ /* found a factor */ if (D.C2lt) y = RgX_int_normalize(y); /* monic */ gel(fa,cnt++) = y; /* fix up pol */ pol = q; for (i=j=k=1; i <= lfamod; i++) { /* remove used factors */ if (j <= K && i == ind[j]) j++; else { famod[k] = 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]]; update_target(&D, pol); 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(pol) > 0) { /* leftover factor */ if (D.C2lt) pol = RgX_int_normalize(pol); if (lfamod >= 2*K) { /* restore leading coefficient [#930] */ if (lt) pol = RgX_Rg_mul(pol, lt); *done = 0; /* ... may still be reducible */ } setlg(famod, lfamod+1); gel(fa,cnt++) = pol; } 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_COL); init_div_data(&D, pol, T->L->topowden); 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): 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 = DEFAULTPREC + divsBIL( gexpo(M) ); for(;;) { R = Q_from_QR(M, prec); if (R) break; prec = (prec-1)<<1; } 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(precer,"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->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 ltdn, GEN init_fa, long nbf, long fl, nflift_t *L) { GEN z, Cltdnx_r, C2ltdnpol, C = L->topowden; GEN Cltdn = mul_content(C, ltdn); /* t_INT */ GEN C2ltdn = mul_content(C,Cltdn); /* t_INT */ long i, m; 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); Cltdnx_r = deg1pol_shallow(Cltdn? Cltdn: gen_1, NULL, varn(pol)); C2ltdnpol = C2ltdn? RgX_Rg_mul(pol, C2ltdn): 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; byteptr pt = diffptr; ulong pp = 0; 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); /* select pr such that pol has the smallest number of factors, ct attempts */ for (;;) { 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 */ NEXT_PRIME_VIADIFF_CHECK(pp, pt); if (! umodiu(bad,pp)) continue; if (*lt) { ltp = umodiu(*lt, pp); if (!ltp) continue; } ap = utoipos(pp); r = get_good_factor(nfpol, ap, maxf); if (!r) continue; apr = primedec_apply_kummer(nf,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 { GEN q; if (ltp) red = FqX_normalize(red, aT,ap); if (!FqX_is_squarefree(red,aT,ap)) { avma = av2; continue; } q = powiu(ap, degpol(aT)); anbf = fl == FACTORS? FqX_split_by_degree(&fa, red, q, aT, ap) : FqX_split_deg1(&fa, red, q, 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) 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 P, x0, 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)); for (i=lx-1; i>0; i--) { GEN f = gel(fa,i), F = RgXQX_translate(f, x0, T); if (!tmonic) F = Q_primpart(F); F = nfgcd(u, F, T, dent); if (typ(F) != t_POL || degpol(F) == 0) pari_err(talker,"reducible modulus in factornf"); gel(P,i) = QXQX_normalize(F, T); } 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 || typ(T)!=t_POL) pari_err(typeer,"polfnf"); T = Q_primpart(T); tmonic = is_pm1(leading_term(T)); RgX_check_ZX(T,"polfnf"); A = Q_primpart( QXQX_normalize(rnf_fix_pol(T,a,1), T) ); dA = degpol(A); if (dA <= 0) { avma = (pari_sp)(rep + 3); return (dA == 0)? trivfact(): 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) return mkvec(QXQX_normalize(pol, nfpol)); 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); T.ZC = L2_bound(nf, den); T.dn = is_pm1(den)? NULL: 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, mul_content(lt, T.dn), 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 = get_den(&nf, T); pari_sp av = avma; GEN z = gerepilecopy(av, nfsqff(nf, pol, 2, 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 maxf, nfdeg = degpol(nfpol); byteptr pt = diffptr; ulong pp = 0; maxf = get_maxf(nfdeg); for (;;) { NEXT_PRIME_VIADIFF_CHECK(pp, pt); if (! umodiu(bad,pp)) continue; ap = utoipos(pp); r = get_good_factor(nfpol, ap, maxf); if (r) break; } apr = primedec_apply_kummer(nf,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->q, 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, gen_1, 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), l; ulong p = 2; byteptr pt = diffptr+1; GEN T = nf_get_pol(nf), nbroots = NULL; pari_sp av = avma; /* result must be stationnary (counter c) for at least nfdegree+20 loops */ for (l=1;; l++) { GEN old, Tp, F, pf_1; long i, nb, gcdf = 0; NEXT_PRIME_VIADIFF_CHECK(p,pt); Tp = ZX_to_Flx(T,p); if (!Flx_is_squarefree(Tp, p)) continue; 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 > nfdegree + 20) break; } else c = 0; } if (DEBUGLEVEL>5) err_printf("%ld loops\n",l); avma = av; return itos(nbroots); } 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) { /* check that 2 | n and v_p(disc K) >= n/2 */ if (!odd(nfdegree) && vali(disc) >= nfdegree / 2) continue; if (LE[i] == 1) continue; } else { /* check that p-1 | n and v_p(disc K) >= (p-2) n/(p-1) */ long v = Z_lval(disc, p); if (nfdegree % (p-1) == 0 && v >= nfdegree/(p-1) * (p-2)) continue; } nbguessed /= upowuu(p, LE[i]); LE[i] = 0; } if (DEBUGLEVEL>2) timer_printf(&ti, "adding ramification conditions [guess = %ld]", nbguessed); if (nbguessed == 2) return trivroots(); /* Step 2 : choose a prime ideal for local lifting */ av = avma; 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); 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 = (prec<<1)-2; if (DEBUGLEVEL) pari_warn(warnprec,"rootsof1",prec); nf = nfnewprec_shallow(nf,prec); } if (itos(ground(gel(y,2))) != N) pari_err(bugparier,"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; i=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(x[1]) < 0) x = gneg(x); if (signe(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 */ { 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 += 3 * e; } gel(P,i) = w; v = Z_pvalrem(n, p, &n); if (v) { exp += 3*v; 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 -= 3*v; 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) { setlg(P2, j); setlg(E2, j); fa = famat_mul_shallow(fa, 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 += 3*e; 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_FRAC: case t_COMPLEX: case t_POL: case t_RFRAC: break; default: pari_err(talker,"can't factor %Ps",x); } y = cgetg(3,t_MAT); gel(y,1) = mkcolcopy(x); gel(y,2) = mkcol(gen_1); return y; } 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 0. Compute x^n using left-right binary powering */ GEN leftright_pow_u_fold(GEN x, ulong n, void *data, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)) { GEN y; long m, j; pari_sp av = avma, lim = stack_lim(av, 1); if (n == 1) return gcopy(x); m = (long)n; j = 1+bfffo(m); y = x; /* normalize, i.e set highest bit to 1 (we know m != 0) */ m<<=j; j = BITS_IN_LONG-j; /* first bit is now implicit */ for (; j; m<<=1,j--) { if (m < 0) y = msqr(data,y); /* first bit set: multiply by base */ else y = sqr(data,y); if (low_stack(lim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"leftright_pow"); y = gerepilecopy(av, y); } } return gerepilecopy(av, y); } /* assume n != 0, t_INT. Compute x^|n| using left-right binary powering */ GEN leftright_pow_fold(GEN x, GEN n, void *data, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)) { long ln = lgefint(n); if (ln == 3) return leftright_pow_u_fold(x, n[2], data, sqr, msqr); else { GEN nd = int_MSW(n), y = x; long i, m = *nd, j = 1+bfffo((ulong)m); pari_sp av = avma, lim = stack_lim(av, 1); /* normalize, i.e set highest bit to 1 (we know m != 0) */ m<<=j; j = BITS_IN_LONG-j; /* first bit is now implicit */ for (i=ln-2;;) { for (; j; m<<=1,j--) { if (m < 0) y = msqr(data,y); /* first bit set: multiply by base */ else y = sqr(data,y); if (low_stack(lim, stack_lim(av,1))) { if (DEBUGMEM>1) pari_warn(warnmem,"leftright_pow"); y = gerepilecopy(av, y); } } if (--i == 0) return gerepilecopy(av, y); nd=int_precW(nd); m = *nd; j = BITS_IN_LONG; } } } /*******************************************************************/ /* */ /* ROOTS --> MONIC POLYNOMIAL */ /* */ /*******************************************************************/ /* return c = x - u, code = c[1] */ static GEN x_u(GEN u, long code) { GEN c = cgetg(4,t_POL); c[1] = code; gel(c,2) = gneg(u); gel(c,3) = gen_1; return c; } /* compute prod (x - a[i]) */ GEN roots_to_pol(GEN a, long v) { long i, k, code, lx = lg(a); GEN L; if (lx == 1) return pol_1(v); L = cgetg(lx, t_VEC); code = evalsigne(1)|evalvarn(v); 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; 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_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(p1[2])==t_INT && typ(p1[3])==t_INT) {avma=av; return gcopy(y);} p1 = ginv(p1); avma=av; if (typ(p1[2])==t_INT && typ(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_FRAC: return gcdiq(x,y); case t_COMPLEX: if (c_is_rational(y)) return gauss_gcd(x,y); case t_QUAD: return triv_cont_gcd(y,x); case t_PADIC: return padic_gcd(x,y); default: return gen_1; /* t_REAL */ } 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(operi,"g",x,y); return ggcd(gel(y,1), x); case t_COMPLEX: case t_QUAD: return triv_cont_gcd(y,x); case t_PADIC: return padic_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_PADIC: return padic_gcd(x,y); } case t_COMPLEX: /* ty = PADIC or QUAD */ return triv_cont_gcd(x,y); case t_PADIC: /* ty = QUAD */ return triv_cont_gcd(y,x); 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))? gcopy(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(x[1]); switch(ty) { case t_POL: vy = varn(y); if (varncmp(vy,vx) < 0) return cont_gcd_gen(y, x); z = cgetg(3,t_POLMOD); gel(z,1) = gcopy(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(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(operi,"g",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); /* same main variable */ switch(tx) { case t_POL: switch(ty) { case t_POL: if (vx != vy) { if (!signe(y)) return gcopy(x); if (!signe(x)) return gcopy(y); return gen_1; } 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: z=cgetg(3,t_RFRAC); if (ty != t_RFRAC) pari_err(operf,"g",x,y); p1 = RgX_div(gel(y,2), RgX_gcd(gel(x,2), gel(y,2))); tetpil = avma; gel(z,2) = gerepile((pari_sp)z,tetpil,gmul(p1, gel(x,2))); gel(z,1) = ggcd(gel(x,1), gel(y,1)); return z; } pari_err(operf,"g",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 = lg(x[1]); 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 (typ(c) == t_INTMOD || 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(typeer, "content"); } 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); } /* NOT MEMORY CLEAN * 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) */ GEN subresext(GEN x, GEN y, GEN *U, GEN *V) { pari_sp av, av2, tetpil, 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; GEN *gptr[3]; if (!is_extscalar_t(tx) || !is_extscalar_t(ty)) pari_err(typeer,"subresext"); 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; tetpil = avma; z = gmul(z,p1); *U = RgX_Rg_mul(uze,cu); *V = RgX_Rg_mul(vze,cv); gptr[0] = &z; gptr[1] = U; gptr[2] = V; gerepilemanysp(av,tetpil,gptr,3); 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 || ty!=t_POL || varncmp(varn(x),varn(y))) pari_err(typeer,"RgX_extgcd"); 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, 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 || typ(T)!=t_POL || varncmp(varn(x),varn(T))) pari_err(typeer,"RgXQ_ratlift"); if (amax+bmax>=degpol(T)) pari_err(talker, "ratlift: must have amax+bmax < deg(T)"); if (!signe(T)) pari_err(zeropoler,"RgXQ_ratlift"); vx = varn(T); av = avma; 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, b; GEN c; if (n == 1) return x; a=1; while (n >= (b=a+a)) a=b; /* 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 gen_0; 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 gen_0; } av2 = avma; s = Lazard(leading_term(Q), s, degpol(P)); if (sig == -1) s = gneg(s); if (cP) s = gmul(s, gpowgs(cP,dQ)); if (cQ) s = gmul(s, gpowgs(cQ,dP)); if (sol) { *sol = P; gerepileall(av, 2, &s, sol); return s; } return (avma == av2)? gerepilecopy(av, s): gerepileupto(av, s); } /* Return resultant(P,Q). If sol != NULL: set *sol to the last non-zero * 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 || typ(y)!=t_POL) pari_err(typeer,"sylvestermatrix"); if (varn(x) != varn(y)) pari_err(talker,"not the same variables in sylvestermatrix"); x = sylvestermatrix_i(x,y); lx = lg(x); for (i=1; i 0) { x = gsubst(x,v,pol_x(0)); if (typ(x) == t_POL && varn(x) == 0) return x; } return scalarpol(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(flagerr,"polresultant"); } if (m) x = gsubst(x,MAXVARN,pol_x(0)); return gerepileupto(av,x); } /*******************************************************************/ /* */ /* 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(talker,"incorrect variable priorities in RgXQ_charpoly"); 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) { long tx = typ(x), vQ = varn(Q), dQ = degpol(Q), vx, vT; pari_sp av = avma; GEN T; if (v < 0) v = 0; nf = checknf(nf); T = nf_get_pol(nf); vT = varn(T); Q = rnf_fix_pol(T,Q,0); if (tx == t_POLMOD) { GEN M = gel(x,1); long vM = varn(M); int ok = 1; if (vM == vQ) { if (!RgX_equal(M, Q)) ok = 0; } else if (vM == vT) { if (!RgX_equal(M, T)) ok = 0; } else ok = 0; if (!ok) pari_err(consister,"rnfcharpoly"); x = gel(x, 2); tx = typ(x); } if (tx != t_POL) { if (!is_rational_t(tx)) pari_err(typeer,"rnfcharpoly"); return caract_const(av, x, v, dQ); } vx = varn(x); if (vx == vT) return caract_const(av, mkpolmod(x,T), v, dQ); if (vx != vQ) pari_err(typeer,"rnfcharpoly"); x = rnf_fix_pol(T,x,0); 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 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; if (!signe(x) || !dx) return RgX_get_0(x); Tx = RgX_simpletype(x); if (Tx == t_INT) return ZX_disc(x); if (Tx == t_FRAC) return QX_disc(x); 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); 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(typeer,"poldisc"); 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(typeer,"reduceddiscsmith"); if (n<=0) pari_err(constpoler,"reduceddiscsmith"); RgX_check_ZX(x,"poldiscreduced"); if (!gequal1(gel(x,n+2))) pari_err(talker,"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 || degq&1) r=gneg_i(r); sl = gsigne(gel(r,dr-1)); sr = b? gsigne(poleval(r,b)): sl; if (sr) { if (!s) s=sr; else if (sr!=s) { s= -s; r1--; } } sr = a? gsigne(poleval(r,a)): ((dr&1)? sl: -sl); if (sr) { if (!t) t=sr; else if (sr!=t) { t= -t; r1++; } } if (dr==3) { avma=av; return r1; } u=v; p1 = g; g = gabs(leading_term(u),DEFAULTPREC); switch(degq) { case 0: break; case 1: p1 = gmul(h,p1); h = g; break; default: p1 = gmul(gpowgs(h,degq),p1); h = gdivexact(gpowgs(g,degq), gpowgs(h,degq-1)); } v = RgX_Rg_divexact(r,p1); if (low_stack(lim,stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"polsturm, dr = %ld",dr); gerepileall(av,4,&u,&v,&g,&h); } } } /***********************************************************************/ /** **/ /** GENERIC EXTENDED GCD **/ /** **/ /***********************************************************************/ static GEN RgXQ_inv_inexact(GEN x, GEN y) { pari_sp av = avma; long i, dx = degpol(x), dy = degpol(y), dz = dx+dy; GEN v, z; if (dx < 0 || dy < 0) pari_err(talker,"non-invertible polynomial in RgXQ_inv"); v = RgM_solve(sylvestermatrix(y,x), col_ei(dz, dz)); if (!v) pari_err(talker,"non-invertible polynomial in RgXQ_inv"); z = cgetg(dy+2,t_POL); z[1] = y[1]; for (i=2; i 0) { d = (vx == NO_VARIABLE)? ginv(x): gred_rfrac_simple(gen_1, x); return scalarpol(d, vy); } if (lg(x)!=3) pari_err(talker,"non-invertible polynomial in RgXQ_inv"); x = gel(x,2); vx = gvar(x); } if (isinexact(x) || isinexact(y)) return RgXQ_inv_inexact(x,y); av = avma; d = subresext(x,y,&u,&v/*junk*/); if (gequal0(d)) pari_err(talker,"non-invertible polynomial in RgXQ_inv"); if (typ(d) == t_POL && varn(d) == vx) { if (lg(d) > 3) pari_err(talker,"non-invertible polynomial in RgXQ_inv"); d = gel(d,2); } d = gdiv(u,d); if (typ(d) != t_POL || varn(d) != vy) d = scalarpol(d, vy); return gerepileupto(av, d); } /*Assume vx 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 gcopy(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 vecbezout(GEN x, GEN y) { GEN z=cgetg(4,t_VEC); gel(z,3) = gbezout(x,y,(GEN*)(z+1),(GEN*)(z+2)); return z; } GEN vecbezoutres(GEN x, GEN y) { GEN z=cgetg(4,t_VEC); gel(z,3) = subresext(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(typeer,"ginvmod"); 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(typeer,"newtonpoly"); 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] = ggval(gel(x,a),p); for (a=0, ind=1; a= 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; const ulong q = p_1 >>1; long i, x, l ; GEN L; if (p <= 19) { /* quick trivial cases */ switch(p) { case 2: return 1; case 7: case 17: return 3; default: return 2; } } if (!L0) { ulong t; (void)u_lvalrem(q, 2, &t); L0 = L = gel(factoru(t), 1); l = lg(L); } else { l = lg(L0); L = cgetg(l, t_VECSMALL); } for (i=1; i= 0) return 0; for (i = lg(L)-1; i; i--) { GEN t = Fp_pow(x, gel(L,i), p); if (equalii(t, p_1) || is_pm1(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; long l, i; GEN x, q, 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); q = shifti(p_1, -1); if (!L0) { GEN t; (void)Z_lvalrem(q, 2, &t); L0 = L = gel(Z_factor(t), 1); l = lg(L); } else { l = lg(L0); L = cgetg(l, t_VEC); } for (i=1; i 2^BIL */ ulong pgener_Zl(ulong p) { ulong x; if (p == 2) pari_err(talker,"primitive root mod 2^3 does not exist"); /* only p < 2^32 such that znprimroot(p) != znprimroot(p^2) */ if (p == 40487) return 40492; x = pgener_Fl(p); #ifdef LONG_IS_64BIT { pari_sp av = avma; GEN q = sqru(p); GEN y = Fp_powu(utoipos(x), p-1, q); if (is_pm1(y)) { x += p; if (x < p) pari_err(talker, "p too large in pgener_Zl"); } avma = av; } #endif return x; } /* p prime. Return a primitive root modulo p^e, e > 1 */ GEN pgener_Zp(GEN p) { GEN x, y; if (lgefint(p) == 3 && !(p[2] & HIGHBIT)) return utoipos( pgener_Zl(p[2]) ); x = pgener_Fp(p); y = Fp_pow(x, subis(p,1), sqri(p)); if (is_pm1(y)) x = addii(x,p); else avma = (pari_sp)x; return x; } static GEN gener_Zp(GEN q) { GEN p; long e = Z_isanypower(q, &p); return e > 1? pgener_Zp(p): pgener_Fp(q); } GEN znprimroot(GEN m) { pari_sp av; GEN x, z; if (typ(m) != t_INT) pari_err(arither1); if (!signe(m)) pari_err(talker,"zero modulus in znprimroot"); if (is_pm1(m)) return mkintmodu(0,1); z = cgetg(3, t_INTMOD); m = absi(m); gel(z,1) = m; av = avma; switch(mod4(m)) { case 0: /* m = 0 mod 4 */ if (!equaliu(m,4)) /* m != 4, non cyclic */ pari_err(talker,"primitive root mod %Ps does not exist", m); x = utoipos(3); break; case 2: /* m = 2 mod 4 */ m = shifti(m,-1); /* becomes odd */ if (is_pm1(m)) { x = gen_1; break; } x = gener_Zp(m); if (!mod2(x)) x = addii(x,m); break; default: /* m odd */ x = gener_Zp(m); break; } gel(z,2) = gerepileuptoint(av, x); return z; } GEN znstar(GEN N) { GEN res = cgetg(4,t_VEC), z, P, E, cyc, gen, mod; long i, j, nbp, sizeh; pari_sp av; if (typ(N) != t_INT) pari_err(arither1); if (!signe(N)) { gel(res,1) = gen_2; gel(res,2) = mkvec(gen_2); gel(res,3) = mkvec(gen_m1); return res; } if (cmpiu(N,2) <= 0) { gel(res,1) = gen_1; gel(res,2) = cgetg(1,t_VEC); gel(res,3) = cgetg(1,t_VEC); return res; } N = absi(N); /* copy needed: will be part of res (mkintmod) */ av = avma; z = Z_factor(N); P = gel(z,1); E = gel(z,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; } } gerepileall(av, 2, &cyc, &gen); gel(res,1) = ZV_prod(cyc); gel(res,2) = cyc; for (i = 1; i <= sizeh; i++) gel(gen,i) = mkintmod(gel(gen,i), N); gel(res,3) = gen; return res; } /*********************************************************************/ /** **/ /** INTEGRAL SQUARE ROOT **/ /** **/ /*********************************************************************/ GEN sqrtint(GEN a) { if (typ(a) != t_INT) pari_err(arither1); switch (signe(a)) { case 1: return sqrti(a); case 0: return gen_0; default: pari_err(talker, "negative integer in sqrtint"); } return NULL; /* not reached */ } /*********************************************************************/ /** **/ /** PERFECT SQUARE **/ /** **/ /*********************************************************************/ static int carremod(ulong A) { const int carresmod64[]={ 1,1,0,0,1,0,0,0,0,1, 0,0,0,0,0,0,1,1,0,0, 0,0,0,0,0,1,0,0,0,0, 0,0,0,1,0,0,1,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}; const int carresmod63[]={ 1,1,0,0,1,0,0,1,0,1, 0,0,0,0,0,0,1,0,1,0, 0,0,1,0,0,1,0,0,1,0, 0,0,0,0,0,0,1,1,0,0, 0,0,0,1,0,0,1,0,0,1, 0,0,0,0,0,0,0,0,1,0, 0,0,0}; const int carresmod65[]={ 1,1,0,0,1,0,0,0,0,1, 1,0,0,0,1,0,1,0,0,0, 0,0,0,0,0,1,1,0,0,1, 1,0,0,0,0,1,1,0,0,1, 1,0,0,0,0,0,0,0,0,1, 0,1,0,0,0,1,1,0,0,0, 0,1,0,0,1}; const int carresmod11[]={1,1,0,1,1,1,0,0,0,1, 0}; return (carresmod64[A & 0x3fUL] && carresmod63[A % 63UL] && carresmod65[A % 65UL] && carresmod11[A % 11UL]); } /* emulate Z_issquareall on single-word integers */ long uissquareall(ulong A, ulong *sqrtA) { if (!A) { *sqrtA = 0; return 1; } if (carremod(A)) { ulong a = usqrtsafe(A); if (a * a == A) { *sqrtA = a; return 1; } } return 0; } long Z_issquareall(GEN x, GEN *pt) { pari_sp av; GEN y, r; switch(signe(x)) { case -1: return 0; case 0: if (pt) *pt=gen_0; return 1; } if (lgefint(x) == 3) { ulong a; if (!uissquareall((ulong)x[2], &a)) return 0; if (pt) *pt = utoipos(a); return 1; } if (!carremod(umodiu(x, 64*63*65*11))) return 0; av = avma; y = sqrtremi(x, &r); if (r != gen_0) { avma = av; return 0; } if (pt) { *pt = y; avma = (pari_sp)y; } else avma = av; return 1; } /* a t_INT, p prime */ long Zp_issquare(GEN a, GEN p) { long v; GEN ap; if (!signe(a) || gequal1(a)) return 1; v = Z_pvalrem(a, p, &ap); if (v&1) return 0; return equaliu(p, 2)? umodiu(ap, 8) == 1 : kronecker(ap,p) == 1; } static int is_char_2(GEN a) { long j; GEN b; switch(typ(a)) { case t_INTMOD: b = gel(a,1); if (!mod2(b)) { if (!equaliu(b, 2)) pari_err(impl, "issquare for this input"); return 1; } return 0; case t_FFELT: if (equaliu(FF_p_i(a), 2)) return 1; return 0; case t_POLMOD: if (is_char_2(gel(a,1)) || is_char_2(gel(a,2))) return 1; return 0; case t_POL: for (j = 2; j < lg(a); j++) if (is_char_2(gel(a,j))) return 1; return 0; } return 0; } static long polissquareall(GEN x, GEN *pt) { pari_sp av; long v, l = degpol(x); GEN y, a, b; if (!signe(x)) { if (pt) *pt = gcopy(x); return 1; } if (pt) *pt = gen_0; if (l&1) return 0; /* odd degree */ av = avma; v = RgX_valrem(x, &x); if (v) { l = degpol(x); if (l&1) return 0; } a = gel(x,2); switch (typ(a)) { case t_INT: y = Z_issquareall(a,&b)? gen_1: gen_0; break; case t_POL: y = polissquareall(a,&b)? gen_1: gen_0; break; default: y = gissquare(a); b = NULL; break; } if (y == gen_0) { avma = av; return 0; } if (!l) { if (!pt) { avma = av; return 1; } if (!b) b = gsqrt(a,DEFAULTPREC); y = scalarpol(b, varn(x)); goto END; } if (is_char_2(x)) { long i, lx; x = gmul(x, mkintmod(gen_1, gen_2)); lx = lg(x); if ((lx-3) & 1) { avma = av; return 0; } for (i = 3; i < lx; i+=2) if (!gequal0(gel(x,i))) { avma = av; return 0; } if (pt) { y = cgetg((lx+3) / 2, t_POL); for (i = 2; i < lx; i+=2) if (!gissquareall(gel(x,i), &gel(y, (i+2)>>1))) { avma = av; return 0; } y[1] = evalsigne(1) | evalvarn(varn(x)); goto END; } else { for (i = 2; i < lx; i+=2) if (!gissquare(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,2+l),0)); if (!RgX_equal(gsqr(y), x)) { avma = av; return 0; } if (!pt) { avma = av; return 1; } if (!gequal1(a)) { if (!b) b = gsqrt(a,DEFAULTPREC); y = gmul(b, y); } } END: *pt = v? gerepilecopy(av, RgX_shift_shallow(y, v >> 1)): gerepileupto(av, y); return 1; } GEN gissquareall(GEN x, GEN *pt) { long l, tx = typ(x); GEN F; pari_sp av; if (!pt) return gissquare(x); if (is_matvec_t(tx)) { GEN t, y, z; long i; l = lg(x); y = cgetg(l,tx); z = cgetg(l,tx); for (i=1; i= e) { gel(L, i) = mkintmod(gen_0, powiu(p, e)); continue; } if (odd(v)) { avma = av; return gen_0; } t = cvtop(b, gel(P,i), e - v); if (gissquare(t) != gen_1) { avma = av; return gen_0; } t = gtrunc(Qp_sqrt(t)); if (v) t = mulii(t, powiu(p, v>>1)); gel(L,i) = mkintmod(t, powiu(p, e)); } *pt = gerepileupto(av, chinese1_coprime_Z(L)); return gen_1; } case t_FFELT: return FF_issquareall(x, pt)? gen_1: gen_0; default: pari_err(typeer, "gissquareall"); return NULL; /* not reached */ } return l? gen_1: gen_0; } GEN gissquare(GEN x) { pari_sp av; GEN p1,a,p; long l, i, v; switch(typ(x)) { case t_INT: return Z_issquare(x)? gen_1: gen_0; case t_REAL: return (signe(x)>=0)? gen_1: gen_0; case t_INTMOD: { GEN b, q; long w; a = gel(x,2); if (!signe(a)) return gen_1; av = avma; q = gel(x,1); v = vali(q); if (v) /* > 0 */ { long dv; w = vali(a); dv = v - w; if (dv > 0) { if (w & 1) { avma = av; return gen_0; } if (dv >= 2) { b = w? shifti(a,-w): a; if ((dv>=3 && mod8(b) != 1) || (dv==2 && mod4(b) != 1)) { avma = av; return gen_0; } } } q = shifti(q, -v); } /* q is now odd */ i = kronecker(a,q); if (i < 0) { avma = av; return gen_0; } if (i==0) { GEN d = gcdii(a,q); p = gel(Z_factor(d),1); l = lg(p); for (i=1; i=3 && mod8(a) != 1 ) || (v==2 && mod4(a) != 1)) return gen_0; return gen_1; case t_POL: return polissquareall(x,NULL)? gen_1: gen_0; case t_SER: if (!signe(x)) return gen_1; if (valp(x)&1) return gen_0; return gissquare(gel(x,2)); case t_RFRAC: av = avma; a = gissquare(gmul(gel(x,1),gel(x,2))); avma = av; return a; case t_VEC: case t_COL: case t_MAT: p1 = cgetg_copy(x, &l); for (i=1; i= -10 || !equalii(powiu(y, p), *x)) return 0; *k *= p; *x = y; *logx = u; return 1; } static long polispower(GEN x, GEN K, GEN *pt) { pari_sp av; long v, l = degpol(x), k = itos(K); GEN y, a, b; if (!signe(x)) return 1; if (l % k) return 0; /* degree not multiple of k */ v = RgX_valrem(x, &x); if (v % k) return 0; av = avma; a = gel(x,2); b = NULL; if (!ispower(a, K, &b)) { avma = av; return 0; } av = avma; if (degpol(x)) { x = RgX_Rg_div(x,a); y = gtrunc(gsqrtn(RgX_to_ser(x,lg(x)), K, NULL, 0)); if (!RgX_equal(powgi(y, K), x)) { avma = av; return 0; } } else y = pol_1(varn(x)); 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, NULL); } 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. */ static 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; } p_1 = subis(p,1); K = gcdii(K, p_1); if (equaliu(K, 2)) { r = kronecker(x,p); avma = av; return r; } x = Fp_pow(x, diviiexact(p_1,K), p); avma = av; return equali1(x); } long ispower(GEN x, GEN K, GEN *pt) { GEN z; if (!K) return gisanypower(x, pt); if (typ(K) != t_INT) pari_err(typeer, "ispower"); if (signe(K) <= 0) pari_err(talker, "non-positive exponent %Ps in ispower",K); if (is_pm1(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: { GEN L, P, E, q = gel(x,1), a = gel(x,2); pari_sp av; long i, l; if (!signe(a)) { if (pt) *pt = gcopy(x); return 1; } /* a != 0 */ av = avma; L = Z_factor(q); P = gel(L,1); l = lg(P); E = gel(L,2); L = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN p = gel(P,i), t, b; long w, e = itos(gel(E,i)), v = Z_pvalrem(a, p, &b); ulong r; if (v >= e) { gel(L, i) = mkintmod(gen_0, powiu(p, e)); continue; } w = udivui_rem(v, K, &r); if (r) { avma = av; return 0; } /* b unit mod p */ if (e - v == 1) { /* mod p: faster */ if (!Fp_ispower(b, K, p)) { avma = av; return 0; } if (pt) t = Fp_sqrtn(b, K, p, NULL); } else { /* mod p^{2 +} */ t = cvtop(b, gel(P,i), e - v); if (!ispower(t, K, &t)) { avma = av; return 0; } t = gtrunc(t); } if (pt) { if (w) t = mulii(t, powiu(p, w)); gel(L,i) = mkintmod(t, powiu(p, e)); } } if (pt) *pt = gerepileupto(av, chinese1_coprime_Z(L)); return 1; } 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(typeer, "ispower"); 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, NULL)) 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(talker, "missing exponent"); return 0; /* not reached */ } /* 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, j, l, k; GEN logx, y, fa, P, E, Pe, Ee; byteptr d = diffptr; ulong mask, p = 0, ex0 = 11, e = 0, e2; if (absi_cmp(x, gen_2) < 0) return 0; /* -1,0,1 */ x = absi(x); /* Z_lvalrem_stop assigns to x */ k = 1; P = cgetg(26 + 1, t_VECSMALL); E = cgetg(26 + 1, t_VECSMALL); /* trial division */ for(l = 1;;) { int stop; NEXT_PRIME_VIADIFF(p,d); if (p > 102) break; v = Z_lvalrem_stop(x, p, &stop); if (v) { P[l] = p; E[l] = v; l++; e = cgcd(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, le; 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; } } if (e2 == 1) goto END; fa = factoru(e2); Pe = gel(fa,1); le = lg(Pe); Ee = gel(fa,2); for (i = 1; i < le; i++) { p = Pe[i]; for (j = 0; j < Ee[i]; j++) { if (!is_kth_power(x, p, &y, NULL)) break; k *= p; x = y; } } } else { /* any prime divisor of x is > 102 */ const double LOG2_103 = 6.6865; /* lower bound for log_2(103) */ while (Z_issquareall(x, &y)) { k <<= 1; x = y; } mask = 7; while ( (ex = is_357_power(x, &y, &mask)) ) { k *= ex; x = y; } /* cut off at 4 bits which seems to be about optimum; for primes * >> 10^3 the modular checks are no longer competitively fast */ while ( (ex = is_pth_power(x, &y, &ex0, 4)) ) { k *= ex; x = y; } if (DEBUGLEVEL>4) err_printf("Z_isanypower: now k=%ld, x=%Ps\n", k, x); do { if (!*d) { p = unextprime(ex0); break; } NEXT_PRIME_VIADIFF(p,d); } while (p < ex0); /* upper bound for log(x) / log(103) */ e2 = (long)((expi(x) + 1) / LOG2_103); logx = logr_abs( itor(x, DEFAULTPREC + (lg(x)-2) / p) ); while (p < e2) { if (pow_check(p, &x, &logx, &k)) { e2 = (long)((expi(x) + 1) / LOG2_103); continue; /* if success, retry same p */ } if (*d) NEXT_PRIME_VIADIFF(p, d); else p = unextprime(p+1); } } 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 = is_pm1(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<>= r; } if (x1 & y1 & 2) s = -s; z = y1 % x1; y1 = x1; x1 = z; } return (y1 == 1)? s: 0; } GEN gkronecker(GEN x, GEN y) { return map_proto_lGG(kronecker,x,y); } long kronecker(GEN x, GEN y) { pari_sp av = avma, lim; long s = 1, r; ulong xu, yu; if (typ(x) != t_INT || typ(y) != t_INT) pari_err(arither1); 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); } 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 **/ /** **/ /*********************************************************************/ #define eps(t) (((signe(t)*(mod2BIL(t)))&3)==3) long hilbertii(GEN x, GEN y, GEN p) { pari_sp av; long a, b, z; GEN u, v; if (!p) return (signe(x)<0 && signe(y)<0)? -1: 1; if (is_pm1(p)) pari_err(talker,"p = 1 in hilbert()"); av = avma; a = odd(Z_pvalrem(x,p,&u)); b = odd(Z_pvalrem(y,p,&v)); if (equaliu(p, 2)) { z = (eps(u) && eps(v))? -1: 1; if (a && gome(v)) z = -z; if (b && gome(u)) z = -z; } else { z = (a && b && eps(p))? -1: 1; if (a && kronecker(v,p)<0) z = -z; if (b && kronecker(u,p)<0) z = -z; } avma = av; return z; } static void err_at2(void) {pari_err(talker, "insufficient precision for p = 2 in hilbert");} long hilbert(GEN x, GEN y, GEN p) { pari_sp av; long tx, ty, z; GEN p1, p2; if (gequal0(x) || gequal0(y)) return 0; av = avma; tx = typ(x); ty = typ(y); if (tx > ty) swapspec(x,y, tx,ty); if (p) { if (typ(p) != t_INT) pari_err(typeer,"hilbert"); if (signe(p) <= 0) p = NULL; } switch(tx) /* <= ty */ { case t_INT: switch(ty) { case t_INT: return hilbertii(x,y,p); case t_REAL: return (signe(x)<0 && signe(y)<0)? -1: 1; case t_INTMOD: p = gel(y,1); if (equaliu(p,2)) err_at2(); return hilbertii(x, gel(y,2), p); case t_FRAC: z = hilbertii(x, mulii(gel(y,1),gel(y,2)), p); avma = av; return z; case t_PADIC: p = gel(y,2); if (equaliu(p,2) && precp(y) <= 1) err_at2(); p1 = odd(valp(y))? mulii(p,gel(y,4)): gel(y,4); z = hilbertii(x, p1, p); avma = av; return z; } break; case t_REAL: if (ty != t_FRAC) break; if (signe(x) > 0) return 1; return signe(y[1])*signe(y[2]); case t_INTMOD: p = gel(x,1); if (equaliu(p,2)) err_at2(); switch(ty) { case t_INTMOD: if (!equalii(p, gel(y,1))) break; return hilbertii(gel(x,2),gel(y,2),p); case t_FRAC: return hilbert(gel(x,2),y,p); case t_PADIC: if (!equalii(p, gel(y,2))) break; return hilbert(gel(x,2),y,p); } break; case t_FRAC: p1 = mulii(gel(x,1),gel(x,2)); switch(ty) { case t_FRAC: p2 = mulii(gel(y,1),gel(y,2)); z = hilbertii(p1,p2,p); avma = av; return z; case t_PADIC: z = hilbert(p1,y,NULL); avma = av; return z; } break; case t_PADIC: p = gel(x,2); if (ty != t_PADIC || !equalii(p,gel(y,2))) break; if (equaliu(p,2) && (precp(x) <= 1 || precp(y) <= 1)) err_at2(); p1 = odd(valp(x))? mulii(p,gel(x,4)): gel(x,4); p2 = odd(valp(y))? mulii(p,gel(y,4)): gel(y,4); z = hilbertii(p1,p2,p); avma = av; return z; } pari_err(talker,"forbidden or incompatible types in hilbert"); return 0; /* not reached */ } #undef eps #undef ome #undef gome /*******************************************************************/ /* */ /* 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(talker,"composite modulus in Fl_sqrt: %lu",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(talker,"composite modulus in Fl_sqrt: %lu",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 z, u2 = sqri(u), v2 = sqri(v); v = subii(sqri(addii(v,u)), addii(u2,v2)); u = addii(u2, mulii(v2,n)); z = cgetg(3, t_VEC); /* NOT mkvec2: must be gerepileupto-able */ gel(z,1) = modii(u,p); gel(z,2) = modii(v,p); return z; } /* 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 z, b = remii(mulii(a,v), p); u = subii(mului(t,d2), mulii(b,addii(u,d))); v = subii(d2, mulii(b,v)); z = cgetg(3, t_VEC); /* NOT mkvec2: must be gerepileupto-able */ gel(z,1) = modii(u,p); gel(z,2) = modii(v,p); return z; } /* 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 = leftright_pow_fold(mkvec2(u, gen_1), pov2, mkvec4(a,p,n,u), sqrt_Cipolla_sqr, sqrt_Cipolla_msqr); u = gel(y,1); v = gel(y,2); /* 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(v,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 || typ(p) != t_INT) pari_err(arither1); if (signe(p) <= 0 || is_pm1(p)) pari_err(talker,"not a prime in Fp_sqrt"); 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 * bit_accuracy(lgefint(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(talker,"composite modulus in Fp_sqrt: %Ps",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(talker,"composite modulus in Fp_sqrt: %Ps",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; !is_pm1(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 (!is_pm1(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 i,lx, 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: z = cgetg(3, t_POLMOD); if (varn(gel(x,1))!=varn(gel(y,1))) pari_err(talker,"incompatible variables in chinese"); if (RgX_equal(gel(x,1),gel(y,1))) /* same modulus */ { gel(z,1) = gcopy(gel(x,1)); gel(z,2) = chinese(gel(x,2),gel(y,2)); return z; } av = avma; d = RgX_extgcd(gel(x,1),gel(y,1),&u,&v); p2 = gsub(gel(y,2), gel(x,2)); if (!gequal0(gmod(p2, d))) break; p1 = gdiv(gel(x,1),d); p2 = gadd(gel(x,2), gmul(gmul(u,p1), p2)); tetpil=avma; gel(z,1) = gmul(p1,gel(y,1)); 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(consister,"Z_chinese"); 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: z = cgetg_copy(x, &lx); z[1] = x[1]; if (lx != lg(y) || varn(x) != varn(y)) break; 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); int base_is_2, use_montgomery; muldata D; 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; } base_is_2 = 0; if (lgefint(A) == 3) switch(A[2]) { case 1: return 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(&A, k, N, lN, &D); if (base_is_2) A = leftright_pow_u_fold(A, k, (void*)&D, &_sqr, &_m2sqr); else A = gen_powu(A, k, (void*)&D, &_sqr, &_mul); if (use_montgomery) { A = _montred(&D, A); if (cmpii(A,N) >= 0) A = subii(A,N); } return 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); 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 = (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; if (lgefint(y) == 3) switch(y[2]) { case 1: avma = av; return 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 = leftright_pow_fold(y, K, (void*)&D, &_sqr, &_m2sqr); else y = gen_pow(y, K, (void*)&D, &_sqr, &_mul); if (use_montgomery) { y = _montred(&D,y); if (cmpii(y,N) >= 0) y = subii(y,N); } 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 const struct bb_group Fp_star={_Fp_mul,_Fp_pow,_Fp_rand,mod2BIL, cmpii,gequal1}; /*********************************************************************/ /** **/ /** 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_eltorder(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 (equalii(p, gen_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 (is_pm1(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(talker,"not an element of (Z/nZ)* in order"); b = gel(x,1); a = gel(x,2); if (!gequal1(gcdii(a,b))) pari_err(talker,"not an element of (Z/nZ)* in order"); 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)* i **/ /** **/ /*********************************************************************/ static GEN _Fp_easylog(void *E, GEN x, GEN g, GEN ord) { pari_sp av = avma; GEN p1, p = (GEN)E; (void)g; if (is_pm1(x)) return gen_0; /* p > 2 */ p1 = addsi(-1, p); if (equalii(p1,x)) /* -1 */ { ord = dlog_get_ord(ord); if (!ord) ord = p1; return gerepileupto(av, shifti(ord,-1)); } avma = av; return NULL; } GEN Fp_log(GEN a, GEN g, GEN ord, GEN p) { return gen_PH_log(a,g,ord,(void*)p,&Fp_star,_Fp_easylog); } /* find a s.t. g^a = x (mod p^k), p prime, k > 0, (x,p) = 1, g primitive root * mod p^2 [ hence mod p^k ] */ #if 0 /* direct Pohlig-Helmann: O(k log p) mul*/ static GEN Zplog2(GEN x, GEN g, GEN p, ulong k, GEN pk) { ulong l; GEN b, c, ct, t, pl, pl_1, q, Q; if (k == 1) return Fp_log(x, g, subis(p,1), p); l = (k+1) >> 1; pl_1 = powiu(p, l-1); pl = mulii(pl_1, p); q = odd(k)? pl_1: pl; Q = subii(pl, pl_1); /* write a = b + Q c, Q = (p-1)p^(l-1), c defined mod q */ b = Zplog2(remii(x, pl), remii(g, pl), p, l, pl); /* g^b = x (mod p^l) */ /* G := g^Q = 1 + t p^l (mod p^k), (t,p) = 1 */ t = diviiexact(subis(Fp_pow(g, Q, pk), 1), pl); /* G^c = 1 + c p^l t (mod p^k) = x g^-b */ ct = diviiexact(subis(Fp_mul(x, Fp_pow(g, negi(b), pk), pk), 1), pl); c = Fp_mul(ct, Fp_inv(t, q), q); return addii(b, mulii(c, Q)); } #else /* use p-adic log: O(log p + k) mul*/ static GEN Zplog(GEN x, GEN g, GEN p, ulong k, GEN pk, GEN o) { GEN b, n = subis(p,1), a = Fp_log(x, g, o?o:n, p); if (k == 1) return a; x = Fp_mul(x, Fp_pow(g, negi(a), pk), pk); b = gdiv(Qp_log(cvtop(x, p, k)), Qp_log(cvtop(Fp_pow(g,n,pk), p, k))); return addii(a, mulii(n, gtrunc(b))); } #endif GEN znlog(GEN x, GEN g, GEN o) { pari_sp av = avma; long k; GEN p, pk; switch (typ(g)) { case t_PADIC: { pk = gel(g,3); k = precp(g); p = gel(g,2); x = Rg_to_Fp(x, pk); if (equaliu(p, 2)) { if (k > 2) pari_err(talker, "not a primitive root in znlog"); avma = av; return is_pm1(x)? gen_0: gen_1; } g = gel(g,4); break; } case t_INTMOD: { long e; pk = gel(g,1); e = mod4(pk); if (e == 0) { if (!equaliu(pk, 4)) pari_err(talker, "not a primitive root in znlog"); x = Rg_to_Fp(x, pk); avma = av; return is_pm1(x)? gen_0: gen_1; } g = gel(g,2); if (e == 2) { if (equaliu(pk, 2)) return gen_0; pk = shifti(pk, -1); if (cmpii(g, pk) >= 0) g = subii(g, pk); } x = Rg_to_Fp(x, pk); k = Z_isanypower(pk, &p); if (!k) { p = pk; k = 1; } break; } default: pari_err(talker,"not an element of (Z/pZ)* in znlog"); return NULL; /* not reached */ } return gerepileuptoint(av, Zplog(x, g, p, k, pk, o)); } GEN Fp_sqrtn(GEN a, GEN n, GEN p, GEN *zeta) { a = modii(a,p); if (!signe(a)) { if (zeta) *zeta = gen_1; return gen_0; } return gen_Shanks_sqrtn(a,n,addis(p,-1),zeta,(void*)p,&Fp_star); } /*********************************************************************/ /** **/ /** FUNDAMENTAL DISCRIMINANTS **/ /** **/ /*********************************************************************/ static long isfund(GEN x) { if (typ(x) != t_INT) pari_err(arither1); return Z_isfundamental(x); } GEN gisfundamental(GEN x) { return map_proto_lG(isfund,x); } long Z_isfundamental(GEN x) { long r; if (!signe(x)) return 0; 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(arither1); 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(talker,"negative argument in factorial function"); 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 && is_pm1(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(talker,"list of numerators too short in sfcontf2"); 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(typeer,"sfcont2"); } 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) > lg(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(typeer,"contfrac0"); if (nmax < 0) pari_err(talker, "negative nmax in contfrac0"); return sfcont2(b,x,nmax); } GEN pnqn(GEN x) { pari_sp av = avma; long i, lx, tx = typ(x); GEN p0, p1, q0, q1, a, p2, q2; if (! is_matvec_t(tx)) pari_err(typeer,"pnqn"); lx = lg(x); if (lx == 1) return matid(2); p0 = gen_1; q0 = gen_0; if (tx != t_MAT) { p1 = gel(x,1); q1 = gen_1; for (i=2; i0) { avma = av; return NULL; } return gerepileupto(av, gdiv(a,b)); } case t_COMPLEX: { GEN t; y = cgetg(3, t_COMPLEX); t = bestappr_mod(gel(x,1),A,B); if (!t) return NULL; gel(y,1) = t; t = bestappr_mod(gel(x,2),A,B); if (!t) return NULL; gel(y,2) = t; return y; } case t_POL: case t_SER: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i 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 precer */ 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)); } /* allow k = NULL: maximal accuracy */ GEN bestappr(GEN x, GEN k) { pari_sp av = avma; long lx, i; GEN p0, p1, p, q0, q1, q, a, y; if (k) { switch(typ(k)) { case t_INT: break; case t_REAL: case t_FRAC: k = gcvtoi(k,&i); break; default: pari_err(talker,"incorrect bound type in bestappr"); } if (signe(k) <= 0) k = gen_1; } switch(typ(x)) { case t_INT: avma = av; return icopy(x); case t_FRAC: if (!k || cmpii(gel(x,2),k) <= 0) { avma = av; return gcopy(x); } 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)); case t_REAL: { long lx; GEN kr; if (!signe(x)) return gen_0; if (!k) return bestappr_max(x); y = x; p1 = gen_1; a = p0 = floorr(x); q1 = gen_0; q0 = gen_1; x = subri(x,a); /* 0 <= x < 1 */ lx = lg(x); if (lx == 2) { cgiv(x); return a; } kr = itor(k, lx); for(;;) { 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; } a = truncr(x); /* truncr(x) may raise precer */ 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)); } case t_COMPLEX: y = cgetg(3, t_COMPLEX); gel(y,1) = bestappr(gel(x,1),k); gel(y,2) = bestappr(gel(x,2),k); return y; case t_POL: case t_SER: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i1) pari_warn(warnmem,"quadunit"); gerepileall(av2,4, &a,&f,&u,&v); } } if (signe(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); setexpo(R,expo(R)-1); R = mulrr(R, divri(addir(u1,rsqd),v)); break; } if (equalii(u,u1)) { R = sqrr(R); setexpo(R,expo(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(talker,"exponent overflow in quadregulator"); 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)); setexpo(t, expo(t)+1); R = addrr(R,t); } return gerepileuptoleaf(av, R); } /*************************************************************************/ /** **/ /** CLASS NUMBER **/ /** **/ /*************************************************************************/ 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(flagerr,"qfbclassno"); } return NULL; /* not reached */ } /* f^h = 1, return order(f) */ static GEN find_order(GEN f, GEN h) { GEN fh, p,e; long i,j,lim; p = Z_factor(h); e =gel(p,2); p =gel(p,1); for (i=1; i */ q = diviiround(hin, h); /* approximate order of G/H */ for (i=1; i < lform; i++) { pari_sp av = avma; fg = powgi(gel(forms,i), h); fh = powgi(fg, q); a = gel(fh,1); if (is_pm1(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(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 */ long c; p1 = fh; for (c=1; ; c++, p1 = gmul(p1,fh)) if (gequal1(gel(p1,1))) break; q = mulsi(-com, find_order(fh, utoipos((ulong)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 = Z_factor(s < 0? absi(x): 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(Z_factor(absi(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, long f) { return redimag(qfisqr(primeform_u(x, f))); } #define MAXFORM 11 #define _low(to, x) { GEN __x = (GEN)(x); to = 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) { pari_sp av = avma, av2, lim; long r2,c,lforms,k,l,i,j,com,s, forms[MAXFORM]; GEN count,index,tabla,tablb,hash,p1,p2,hin,h,f,fh,fg,ftest; GEN Hf, D; byteptr p = diffptr; 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(talker,"discriminant too big in classno"); if (s < 10) s = 200; else if (s < 20) s = 1000; else if (s < 5000) s = 5000; c = lforms = 0; maxprime_check(s); while (c <= s) { long d; NEXT_PRIME_VIADIFF(c,p); k = krois(D,c); if (!k) continue; if (k > 0) { if (lforms < MAXFORM) forms[lforms++] = c; d = c - 1; } else d = c + 1; av2 = avma; affrr(divru(mulur(c,p1),d), p1); avma = av2; } 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 = sqr_primeform(D, forms[0]); 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(talker,"discriminant too large in classno"); p4 = divri(Pi,d); p7 = invr(sqrtr_abs(Pi)); p1 = sqrtr_abs(dr); S = gen_0; half = real2n(-1, prec); if (s > 0) { for (i=1; i<=n; i++) { k = krois(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 { p1 = gdiv(p1,Pi); for (i=1; i<=n; i++) { k = krois(D,i); if (!k) continue; p2 = mulir(sqru(i), p4); p5 = subsr(1, mulrr(p7,incgamc(half,p2,prec))); p5 = addrr(p5, divrr(divru(p1,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(typeer,"hclassno"); 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.5.5/src/basemath/base1.c0000644000175000017500000017656312147140046014637 0ustar billbill/* $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. */ /**************************************************************/ /* */ /* 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(typeer,"checkrnf"); } 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) { if (checknf_i(x)) pari_err(talker,"please apply bnfinit first"); pari_err(typeer,"checkbnf"); } return bnf; } GEN checknf(GEN x) { GEN nf = checknf_i(x); if (!nf) { if (typ(x)==t_POL) pari_err(talker,"please apply nfinit first"); pari_err(typeer,"checknf"); } return nf; } void checkbnr(GEN bnr) { if (typ(bnr)!=t_VEC || lg(bnr)!=7) pari_err(talker,"incorrect bigray field"); (void)checkbnf(bnr_get_bnf(bnr)); } void checkbnrgen(GEN bnr) { checkbnr(bnr); if (lg(bnr[5])<=3) pari_err(talker,"please apply bnrinit(,,1) and not bnrinit(,)"); } void checksqmat(GEN x, long N) { if (typ(x)!=t_MAT) pari_err(talker,"incorrect ideal"); if (lg(x) == 1 || lg(x[1]) != N+1) pari_err(talker,"incorrect matrix for ideal"); } GEN checkbid_i(GEN bid) { if (typ(bid)!=t_VEC || lg(bid)!=6 || lg(bid[1])!=3) return NULL; return bid; } void checkbid(GEN bid) { if (!checkbid_i(bid)) pari_err(typeer,"checkbid"); } void checkprid(GEN id) { if (typ(id) != t_VEC || lg(id) != 6 || typ(id[2]) != t_COL) pari_err(talker,"incorrect prime ideal"); } GEN get_prid(GEN x) { long lx; if (typ(x) != t_VEC) return NULL; lx = lg(x); if (lx == 3) { x = gel(x,1); lx = lg(x); } if (lx != 6 || typ(x[3]) != t_INT) return NULL; return x; } GEN checknfelt_mod(GEN nf, GEN x, const char *s) { GEN T = gel(x,1), a = gel(x,2); if (!RgX_equal_var(T, nf_get_pol(nf))) pari_err(talker, "incompatible modulus in %s:\n mod = %Ps,\n nf = %Ps", s, a, T); return a; } void check_ZKmodule(GEN x, const char *s) { if (typ(x) != t_VEC || lg(x) < 3) pari_err(talker,"not a module in %s", s); if (typ(x[1]) != t_MAT) pari_err(talker,"not a matrix in %s", s); if (typ(x[2]) != t_VEC || lg(x[2]) != lg(x[1])) pari_err(talker,"not a correct ideal list in %s", 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(x[1]) != t_VEC || typ(x[3]) != t_MAT) break; *t = typ_BID; return NULL; case 10: *t = typ_NF; return NULL; case 11: *t = typ_BNF; return x; 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 13: *t = typ_RNF; return NULL; case 14: case 20: *t = typ_ELL; return NULL; } } *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(x[2]) != t_POLMOD) break; return get_nf(gel(x,1),t); 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 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 6 : if (typ(x[1]) != t_VEC || typ(x[3]) != t_MAT) break; *t = typ_BID; return NULL; case 9 : x = gel(x,2); if (typ(x) == t_VEC && lg(x) == 4) *t = typ_GAL; return NULL; case 13: *t = typ_RNF; return NULL; case 14: case 20: *t = typ_ELL; 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: 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(x[1]) != t_VEC || typ(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 14: case 20: return typ_ELL; }break; } 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(notpoler,"tschirnhaus"); if (lg(x) < 4) pari_err(constpoler,"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! */ } if (sk < 0) k = absi(k); fa = Z_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(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 *ptlc = 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 *ptlc) { long i,j, n = degpol(pol); GEN lc = leading_term(pol), fa, P, E, a, POL; if (signe(lc) < 0) POL = ZX_neg(pol); else POL = leafcopy(pol); a = POL+2; lc = gel(a,n); if (is_pm1(lc)) { if (ptlc) *ptlc = gen_1; return POL; } fa = Z_factor_limit(lc,0); lc = 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(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; lc = mulii(lc, 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 (ptlc) *ptlc = lc; 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 *ptlc = 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 *ptlc) { GEN lc = NULL, POL = ZX_primitive_to_monic(pol, ptlc? &lc : NULL); POL = ZX_Z_normalize(POL, ptlc); if (ptlc) *ptlc = gdiv(lc, *ptlc); 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(notpoler,"galois"); n=degpol(x); if (n<=0) pari_err(constpoler,"galois"); 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(impl,"galois of reducible polynomial"); 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 = DEFAULTPREC + (long)(cb*(18./ LOG2 / BITS_IN_LONG)); for(;;) { p1=cleanroots(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 = (prec<<1)-2; } 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(bugparier,"galois (bug1)"); } case 5: z = cgetg(7,t_VEC); ee= cgetg(7,t_VECSMALL); w = cgetg(7,t_VECSMALL); prec = DEFAULTPREC + (long)(cb*(21. / LOG2/ BITS_IN_LONG)); for(;;) { for(;;) { p1=cleanroots(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 = (prec<<1)-2; } 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 = - (bit_accuracy(prec) >> 1); for (l=1; l<=6; l++) if (ee[l] <= pr && gequal0(poleval(p5,gel(w,l)))) break; if (l>6) pari_err(bugparier,"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=(prec<<1)-2; } case 6: z = cgetg(7, t_VEC); prec = DEFAULTPREC + (long)(cb * (42. / LOG2 / BITS_IN_LONG)); for(;;) { for(;;) { p1=cleanroots(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=(prec<<1)-2; } 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=(prec<<1)-2; 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(bugparier,"galois (bug3)"); } } case 7: z = cgetg(36,t_VEC); prec = DEFAULTPREC + (long)(cb*(7. / LOG2 / BITS_IN_LONG)); for(;;) { ind = 0; p1=cleanroots(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 = (prec<<1)-2; } 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(bugparier,"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); } 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) */ static GEN ZC_galoisapply(GEN nf, GEN s, GEN x) { x = nf_to_scalar_or_alg(nf, x); return typ(x) == t_POL? nfpoleval(nf,x,s): scalarcol(x, nf_get_degree(nf)); } 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, b, 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); #if 1 b = FpM_deplin(zk_multable(nf, u), p); #else /* Slower */ b = QX_galoisapplymod(nf, coltoliftalg(nf, pr_get_tau(pr)), aut, p); #endif return mkvec5(p, u, gel(pr,3), gel(pr,4), b); } /* fa : 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: { GEN G, g; long i, lx; switch(lg(x)) { case 1: return cgetg(1, t_MAT); case 3: break; default: pari_err(typeer, "galoisapply"); } g = gel(x,1); G = cgetg_copy(g, &lx); for (i = 1; i < lx; i++) gel(G,i) = galoisapply(nf, aut, gel(g,i)); return mkmat2(g, ZC_copy(gel(x,2))); } } pari_err(typeer,"galoisapply"); 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 (lg(x[1])-1 != nf_get_degree(nf)) break; aut = algtobasis(nf, aut); y = cgetg(lx,t_MAT); for (j=1; j1) pari_err(talker,"ramified prime in idealfrobenius"); f = pr_get_f(pr); n = nf_get_degree(nf); if (f==1) { avma = av; return identity_perm(n); } modpr = nf_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) { pari_sp av = avma; long i, n = nf_get_degree(nf); GEN p, T, modpr = nf_to_Fq_init(nf,&pr,&T,&p); GEN a = pol_x(nf_get_varn(nf)); GEN b = modpr_genFq(modpr); long e = pr_get_e(pr), f = pr_get_f(pr); long coprime = cgcd(e, f) == 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 (idealval(nf, galoisapply(nf, S, pi), pr)==1) { if (coprime) { avma = av; return iso; } else { GEN c = nf_to_Fq(nf, galoisapply(nf, S, b), modpr); if (ZX_equal(a, c)) { avma = av; return iso; } } } avma = ltop; } } pari_err(talker,"no isotrope element not found"); 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); iso = idealinertiagroup(nf, gal, pr); 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, a, 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 = nf_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); a = pol_x(nf_get_varn(nf)); 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 = 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 (!gequal(a, 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(typeer,"get_bnfpol"); 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 || n <= 0) pari_err(constpoler, "nfisincl"); 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); db = nfb? nf_get_disc(nfb): ZX_disc(b); if (fliso) return (gissquare(gdiv(da,db)) == gen_1); if (odd(q) && signe(da) != signe(db)) return 0; fa = Z_factor_limit(absi(da), 0); P = gel(fa,1); E = gel(fa,2); nP = lg(P) - 1; if (!nP) pari_err(talker,"inconsistent data in nfisincl"); for (i=1; i 0) { fa = Z_factor(U); P = gel(fa,1); E = gel(fa,2); } else { P = mkvec(U); E = mkvec(gel(E,nP)); } 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) { long i, j, n, r1, r2; GEN ro = nf_get_roots(nf), v; nf_get_sign(nf, &r1,&r2); n = r1 + (r2<<1); v = cgetg(n+1, t_VEC); for (i = 1; i <= r1; i++) gel(v,i) = gel(ro,i); for (j = i; j <= n; i++) { GEN z = gel(ro,i); gel(v,j++) = z; gel(v,j++) = mkcomplex(gel(z,1), gneg(gel(z,2))); } return v; } /* 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 = (long)((n*er + eBD + log2(n)) / BITS_IN_LONG); } 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, long prec) { nffp_init(F,T,ro,prec); make_M_G(F, 1); } 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(8,t_VEC); long n = degpol(T->x); nffp_t F; get_nf_fp_compo(T, &F, ro, 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; return nf; } static GEN hnffromLLL(GEN nf) { GEN d, x; x = RgXV_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, extraprec, n = degpol(T->x); nffp_t F; extraprec = (long) (0.25 * n / (sizeof(long) / 4)); prec = DEFAULTPREC + extraprec; 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 = (prec<<1)-2 + divsBIL(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); long 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 GEN polred_aux(nfbasic_t *T, GEN *pro, long flag); /* 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 = T->dx, a, z, rev, pow, dpow; long i, n = degpol(x), v = varn(x); if (n == 1) { T->x = deg1pol_shallow(gen_1, gen_m1, v); *pro = NULL; return pol_1(v); } z = polred_aux(T, pro, nf_ORIG | nf_RED); if (typ(z) != t_VEC || !ZX_is_better(gel(z,1),x,&dx)) return NULL; /* no improvement */ rev = QXQ_reverse(gel(z,2), x); x = gel(z,1); if (DEBUGLEVEL>1) err_printf("xbest = %Ps\n",x); /* update T */ pow = QXQ_powers(rev, n-1, x); pow = Q_remove_denom(pow, &dpow); a = T->bas; for (i=2; i<=n; i++) gel(a,i) = QX_ZXQV_eval(gel(a,i), pow, dpow); (void)Z_issquareall(diviiexact(dx,T->dK), &(T->index)); T->basden = get_bas_den(a); T->dx = dx; T->x = x; *pro = NULL; 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(typeer,"get_nfindex"); } D = mulii(D, lc); } if (i <= n) { /* not triangular after all */ bas = Q_remove_denom(bas, &d); if (!d) { avma = av; return D; } mat = RgXV_to_RgM(bas, n); d = diviiexact(powiu(d, n), det(mat)); D = mulii(D,d); } return gerepileuptoint(av, D); } /* monic integral polynomial + integer basis */ static int is_polbas(GEN x) { return (typ(x) == t_VEC && lg(x)==3 && typ(gel(x,1))==t_POL && lg(gel(x,2))-1 == degpol(gel(x,1))); } 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, GEN fa, nfbasic_t *T) { GEN bas, dK, dx, index; long r1; T->basden = NULL; T->lead = gen_1; if (typ(x) == t_POL) { nfmaxord_t S; x = Q_primpart(x); RgX_check_ZX(x, "nfinit"); if (!ZX_is_irred(x)) pari_err(redpoler, "nfinit"); if (flag & nf_RED || !gequal1(gel(x,lg(x)-1))) x = ZX_Q_normalize(x, &(T->lead)); nfmaxord(&S, x, flag, fa); index = S.index; dx = S.dT; dK = S.dK; bas = S.basis; r1 = sturm(x); } else if (is_polbas(x)) { /* monic integral polynomial + integer basis */ bas = gel(x,2); x = gel(x,1); if (typ(bas) == t_MAT) bas = RgM_to_RgXV(bas,varn(x)); index = NULL; dx = NULL; dK = NULL; r1 = sturm(x); } else { /* 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); dx = NULL; r1 = nf_get_r1(nf); } T->x = x; T->r1 = r1; T->dx = dx; T->dK = dK; T->bas = bas; 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; nfbasic_t T; nfbasic_init(x, flag, NULL, &T); nfbasic_add_disc(&T); /* more expensive after set_LLL_basis */ if (T.lead != gen_1 && !(flag & nf_RED)) { pari_warn(warner,"non-monic polynomial. Result of the form [nf,c]"); flag |= nf_RED | nf_ORIG; } if (flag & nf_RED) { GEN ro, 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 (T.lead != gen_1) rev = RgX_Rg_div(rev, T.lead); nf = mkvec2(nf, mkpolmod(rev, T.x)); } } 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(flagerr,"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(talker,"incorrect nf in nfnewprec"); 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 T2_from_embed_norm(GEN x, long r1) { 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 p; } GEN T2_from_embed(GEN x, long r1) { return T2_from_embed_norm(gnorm(x), r1); } 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 */ } 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)); } /* return a defining polynomial for Q(w_i) */ static GEN get_polmin_w(CG_data *d, long k) { GEN g = get_pol(d, gel(d->ZKembed,k)); if (g) (void)ZX_gcd_all(g, ZX_deriv(g), &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(precer,"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; i 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(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; } static long polred_init(nfbasic_t *T, nffp_t *F, CG_data *d) { long e, prec, n = degpol(T->x); 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, prec); d->v = varn(T->x); d->r1= T->r1; return prec; } static GEN polred_aux(nfbasic_t *T, GEN *pro, long flag) { GEN b, y, x = T->x; long i, v = varn(x), l = lg(T->bas); const long orig = flag & nf_ORIG; const long nfred = flag & nf_RED; nffp_t F; CG_data d; (void)polred_init(T, &F, &d); *pro = F.ro; d.ZKembed = F.M; y = cgetg(l, t_VEC); b = cgetg(l, t_COL); gel(y,1) = deg1pol_shallow(gen_1, gen_m1, v); gel(b,1) = gen_1; for (i = 2; i < l; i++) { GEN ch, ai = gel(T->bas,i); ch = get_polmin_w(&d, i); /* if accuracy too low, compute algebraically */ if (!ch) { ch = ZXQ_charpoly(ai, x, v); (void)ZX_gcd_all(ch, ZX_deriv(ch), &ch); } if (ZX_canon_neg(ch) && orig) ai = RgX_neg(ai); if (nfred && degpol(ch) == l-1) return mkvec2(ch, ai); if (DEBUGLEVEL>3) err_printf("polred: generator %Ps\n", ch); if (T->lead != gen_1 && orig) ai = RgX_unscale(ai, ginv(T->lead)); gel(y,i) = ch; gel(b,i) = ai; } 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); } GEN Polred(GEN x, long flag, GEN fa) { pari_sp av = avma; GEN ro; nfbasic_t T; nfbasic_init(x, flag & (nf_PARTIALFACT|nf_RED), fa, &T); return gerepilecopy(av, polred_aux(&T, &ro, flag & nf_ORIG)); } /* FIXME: 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 ordred(GEN x) { pari_sp av = avma; GEN y; if (typ(x) != t_POL) pari_err(typeer,"ordred"); if (!gequal1(leading_term(x))) pari_err(impl,"ordred"); if (!signe(x)) return gcopy(x); y = mkvec2(x, matid(degpol(x))); return gerepileupto(av, Polred(y, 0, NULL)); } 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; } /* 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, S, inv, bound, 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 = RgM_mul(d->M, U); av = avma; bound = d->bound; S = cgetg(N+1, t_VECSMALL); for (i = 1; i <= N; i++) { P = get_polmin_w(d, i); if (!P) pari_err(precer,"chk_gen_init"); S[i] = degpol(P); if (S[i] == N) { /* primitive element */ GEN B = T2_from_embed(gel(d->ZKembed,i), r1); if (gcmp(B,bound) < 0) bound = B ; if (!firstprim) firstprim = i; /* index of first primitive element */ if (DEBUGLEVEL>2) err_printf("chk_gen_init: generator %Ps\n",P); } 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 = d->ZKembed; GEN te = gel(e,i), tu = gel(u,i), tR = gel(R,i); long tS = S[i]; for (j = i; j > firstprim; j--) { u[j] = u[j-1]; e[j] = e[j-1]; R[j] = R[j-1]; S[j] = S[j-1]; } gel(u,firstprim) = tu; gel(e,firstprim) = te; gel(R,firstprim) = tR; S[firstprim] = tS; firstprim++; } } } if (!firstprim) { /* try (a little) to find primitive elements to improve bound */ GEN x = cgetg(N+1, t_VECSMALL), e, B; if (DEBUGLEVEL>1) err_printf("chk_gen_init: difficult field, trying random elements\n"); for (i = 0; i < 10; i++) { for (j = 1; j <= N; j++) x[j] = (long)random_Fl(7) - 3; e = RgM_zc_mul(d->ZKembed, x); P = get_pol(d, e); if (!P) pari_err(precer, "chk_gen_init"); if (!ZX_is_squarefree(P)) continue; if (DEBUGLEVEL>2) err_printf("chk_gen_init: generator %Ps\n",P); B = T2_from_embed(e, r1); if (gcmp(B,bound) < 0) bound = B ; } } if (firstprim != 1) { inv = ginv( split_realimag(d->ZKembed, 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(bugparier,"precision too low in chk_gen_init"); M = mkmat(V); /* 1 */ V = cgetg(N+1, t_VEC); for (i = 1; i <= N; i++,skipfirst++) { /* M = Q-basis of subfield generated by nf.zk[1..i-1] */ GEN Mx, M2; long j, k, h, rkM, dP = S[i]; if (dP == N) break; /* primitive */ Mx = set_mulid(V, d->ZKembed, inv, r1, r2, N, i); if (!Mx) break; /* prec. problem. Stop */ if (dP == 1) continue; rkM = lg(M)-1; M2 = cgetg(N+1, t_MAT); /* we will add to M 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 M * nf.zk[i] */ for (j = 1; j <= rkM; j++) gel(M2,k++) = RgM_RgC_mul(Mx, gel(M,j)); setlg(M2, k); k = 1; M = image(shallowconcat(M, M2)); r = lg(M) - 1; 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(bugparier, "polredabs (precision problem)"); if (prec < d->prec) d->ZKembed = gprec_w(d->ZKembed, prec); return bound; } static GEN findmindisc(GEN y, GEN *pa) { GEN a = *pa, x = gel(y,1), b = gel(a,1), dx; long i, l = lg(y); if (l == 2) { *pa = b; return x; } dx = ZX_disc(x); 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; } /* 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 (T->lead != gen_1) b = RgX_Rg_div(b, T->lead); } 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), RgXV_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 = T2_from_embed(F.ro, T->r1); if (lg(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 = (prec<<1)-2; get_nf_fp_compo(T, &F, NULL, 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|nf_RED), NULL, &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 = polredabs_aux(&T, &u); y = gel(v,1); a = gel(v,2); l = lg(a); 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(arither1); 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; } static int u_IsLucasPsP(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; } /* Fl_BPSW_psp */ int uisprime(ulong n) { Fl_MR_Jaeschke_t S; 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 (!(n & 1)) 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; Fl_init_MR_Jaeschke(&S, n); if (Fl_bad_for_base(&S, 2)) return 0; if (n < 1016801) switch(n) { /* strong 2-pseudoprimes without prime divisors < 103. All have 2 prime * divisor, one of which is <= 661 */ 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 0; default: return 1; } return u_IsLucasPsP(n); } /* assume no prime divisor <= 661 */ int uisprime_nosmalldiv(ulong n) { Fl_MR_Jaeschke_t S; Fl_init_MR_Jaeschke(&S, n); if (Fl_bad_for_base(&S, 2)) return 0; return u_IsLucasPsP(n); } long BPSW_psp(GEN N) { pari_sp av; MR_Jaeschke_t S; int k; if (typ(N) != t_INT) pari_err(arither1); 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; } /* no prime divisor <= 661 */ long BPSW_psp_nosmalldiv(GEN N) { pari_sp av; MR_Jaeschke_t S; int k; if (lgefint(N) == 3) return uisprime_nosmalldiv((ulong)N[2]); av = avma; 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 */ static int BLS_test(GEN N, GEN f) { GEN c1, c2, r, q; if (cmpii(sqri(f), N) < 0) return 1; /* Pocklington case */ q = dvmdii(N, f, &r); if (!is_pm1(r)) return 0; c2 = dvmdii(q, f, &c1); if (Z_issquare(subii(c2, shifti(c1,2)))) return 0; return 1; } /*assume n>=2*/ 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 N is a strong BPSW pseudoprime, Pocklington-Lehmer primality proof. * * flag 0: return gen_1 (prime), gen_0 (composite) * flag 1: return gen_0 (composite), 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, long flag) { pari_sp ltop = avma; long i, l, t = typ(N); int eps; GEN C, F = NULL; if (t == t_VEC) { /* [ N, [p1,...,pk] ], (p_i) list of pseudoprime divisors of N-1 */ F = gel(N,2); N = gel(N,1); t = typ(N); } if (t != t_INT) pari_err(arither1); eps = cmpis(N,2); if (eps<=0) return eps? gen_0: gen_1; if (DEBUGLEVEL>3) err_printf("Pocklington-Lehmer: proving primality of N = %Ps\n", N); N = absi(N); if (!F) { GEN cbrtN = gsqrtn(N, utoi(3), NULL, nbits2prec((expi(N)+2)/3)); GEN N_1 = addis(N,-1), f; F = Z_factor_until(N_1, sqri(floorr(cbrtN))); f = factorback(F); F = gel(F,1); if (!equalii(f, N_1) && !BLS_test(N,f)) { if (DEBUGLEVEL>3) err_printf("Pocklington-Lehmer: N-1 not smooth enough --> Failure. Factored up to %Ps (%.3Ps%%)\n", f, divri(itor(f,3), N)); avma = ltop; return gen_0; } if (DEBUGLEVEL>3) err_printf("Pocklington-Lehmer: N-1 factored up to %Ps! (%.3Ps%%)\n", f, divri(itor(f,3), N)); } if (DEBUGLEVEL>3) err_printf("Pocklington-Lehmer: N-1 smooth enough! Computing certificate\n"); C = cgetg(4,t_MAT); l = lg(F); gel(C,1) = cgetg(l,t_COL); gel(C,2) = cgetg(l,t_COL); gel(C,3) = cgetg(l,t_COL); for(i=1; i3) err_printf("Pocklington-Lehmer: recursively proving primality of p = %Ps\n", p); if (!flag) r = BPSW_isprime(p)? gen_1: gen_0; else { if (BPSW_isprime_small(p)) r = gen_1; else if (expi(p) > 250) r = isprimeAPRCL(p)? gen_2: gen_0; else r = isprimePL(p,flag); } gmael(C,3,i) = r; if (r == gen_0) pari_err(talker,"False prime number %Ps in isprimePL", p); } if (!flag) { avma = ltop; return gen_1; } return gerepileupto(ltop,C); } static long isprimeSelfridge(GEN x) { return (isprimePL(x,0)==gen_1); } /* assume x a BPSW pseudoprime */ long BPSW_isprime(GEN N) { pari_sp av = avma; long l, res; GEN fa, P, F, p, N_1; if (BPSW_isprime_small(N)) return 1; N_1 = subis(N,1); fa = Z_factor_limit(N_1, minss(1L<<19, maxprime())); l = lg(gel(fa,1))-1; p = gcoeff(fa,l,1); F = diviiexact(N_1, powii(p, gcoeff(fa,l,2))); P = gel(fa,1); /* N-1 = F U, F factored, U possibly composite */ if (cmpii(powiu(F, 3), N) >= 0) /* half-smooth, F >= N^(1/3) */ res = BLS_test(N, F) && isprimeSelfridge(mkvec2(N,vecslice(P,1,l-1))); else if (BPSW_psp_nosmalldiv(p)) /* smooth */ res = isprimeSelfridge(mkvec2(N,P)); 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_GL(isprimePL,x,1); case 2: return map_proto_lG(isprimeAPRCL,x); } pari_err(flagerr,"gisprime"); return NULL; } long isprime(GEN x) { return BPSW_psp(x) && BPSW_isprime(x); } /***********************************************************************/ /** **/ /** PRIME NUMBERS **/ /** **/ /***********************************************************************/ /* assume all primes up to 59359 are precomputed */ ulong uprime(long n) { byteptr p; ulong prime; if (n <= 0) pari_err(talker, "n-th prime meaningless if n = %ld",n); if (n < 1000) { p = diffptr; prime = 0; } else if (n < 2000) { n -= 1000; p = diffptr+1000; prime = 7919; } else if (n < 3000) { n -= 2000; p = diffptr+2000; prime = 17389; } else if (n < 4000) { n -= 3000; p = diffptr+3000; prime = 27449; } else if (n < 5000) { n -= 4000; p = diffptr+4000; prime = 37813; } else if (n < 6000) { n -= 5000; p = diffptr+5000; prime = 48611; } else if (n < 10000 || maxprime() < 500000) { n -= 6000; p = diffptr+6000; prime = 59359; } else if (n < 20000) { n -= 10000; p = diffptr+10000; prime = 104729; } else if (n < 30000) { n -= 20000; p = diffptr+20000; prime = 224737; } else if (n < 40000) { n -= 30000; p = diffptr+30000; prime = 350377; } else { n -= 40000; p = diffptr+40000; prime = 479909; } while (n--) NEXT_PRIME_VIADIFF_CHECK(prime,p); return prime; } GEN prime(long n) { return utoipos(uprime(n)); } ulong uprimepi(ulong n) { byteptr p = diffptr+1; ulong prime = 2, res = 0; maxprime_check(n); while (prime < n) { res++; NEXT_PRIME_VIADIFF(prime,p); } return prime == n? res+1: res; } GEN primepi(GEN x) { pari_sp av = avma; GEN N = typ(x) == t_INT? x: gfloor(x); if (typ(N) != t_INT) pari_err(typeer, "primepi"); if (signe(N) <= 0) return gen_0; avma = av; return utoi(uprimepi(itou(N))); } GEN primes(long m) { byteptr p = diffptr; ulong prime = 0; long n = (m < 0)? 0: m; GEN y, z; z = y = cgetg(n+1,t_VEC); while (n--) { NEXT_PRIME_VIADIFF(prime,p); if (!*p) /* use something close to Dusart's bound */ maxprime_check((ulong)(m*( log((double)m*log((double)m))-0.948 ))); gel(++z, 0) = utoipos(prime); } return y; } GEN primes_zv(long m) { byteptr p = diffptr; ulong prime = 0; long n = (m < 0)? 0: m; GEN y, z; z = y = cgetg(n+1,t_VECSMALL); while (n--) { NEXT_PRIME_VIADIFF(prime,p); if (!*p) /* use something close to Dusart's bound */ maxprime_check((ulong)(m*( log((double)m*log((double)m))-0.948 ))); *++z = prime; } return y; } /***********************************************************************/ /** **/ /** 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(typeer,"rmprime"); i = ZV_search(T, p); if (!i) pari_err(talker,"prime %Ps is not in 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 (i 1 in addprimes"); p = addp_union(*T, p); l = lg(p); if (l != lg(*T)) { GEN old = *T, t = cgetalloc(t_VEC, l); for (i = 1; i < l; i++) gel(t,i) = gel(p,i); *T = t; free(old); } avma = av; return *T; } GEN addprimes(GEN p) { return addp(&primetab, p); } static GEN rmprimes(GEN T, GEN prime) { long i,tx; if (!prime) return T; tx = typ(prime); if (is_vec_t(tx)) { if (prime == T) { for (i=1; i < lg(prime); i++) gunclone(gel(prime,i)); setlg(prime, 1); } else { for (i=1; i < lg(prime); i++) rmprime(T, gel(prime,i)); } return T; } rmprime(T, prime); return T; } GEN removeprimes(GEN prime) { return rmprimes(primetab, prime); } pari-2.5.5/src/basemath/trans1.c0000644000175000017500000021316612147140046015043 0ustar billbill/* $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. */ /********************************************************************/ /** **/ /** TRANSCENDENTAL FUNCTIONS **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #ifdef LONG_IS_64BIT static const long SQRTVERYBIGINT = 3037000500L; /* ceil(sqrt(LONG_MAX)) */ static const long CBRTVERYBIGINT = 2097152L; /* ceil(cbrt(LONG_MAX)) */ #else static const long SQRTVERYBIGINT = 46341L; static const long CBRTVERYBIGINT = 1291L; #endif static THREAD GEN geuler, glog2, gpi; void pari_init_floats(void) { geuler = gpi = bernzone = glog2 = NULL; } void pari_close_floats(void) { if (geuler) gunclone(geuler); if (gpi) gunclone(gpi); if (bernzone) gunclone(bernzone); if (glog2) gunclone(glog2); } /********************************************************************/ /** **/ /** PI **/ /** **/ /********************************************************************/ #if 0 /* Ramanujan's formula: * ---- * 53360 (640320)^(1/2) \ (6n)! (545140134 n + 13591409) * -------------------- = / ------------------------------ * Pi ---- (n!)^3 (3n)! (-640320)^(3n) * n>=0 */ GEN piold(long prec) { const long k1 = 545140134, k2 = 13591409, k3 = 640320; const double alpha2 = 47.11041314/BITS_IN_LONG; /* 3log(k3/12) / log(2^BIL) */ GEN p1,p2,p3,tmppi; long l, n, n1; pari_sp av = avma, av2; double alpha; tmppi = cgetr(prec); prec++; n = (long)(1 + (prec-2)/alpha2); n1 = 6*n - 1; p2 = addsi(k2, mulss(n,k1)); p1 = itor(p2, prec); /* initialize mantissa length */ if (prec>=4) l=4; else l=prec; setlg(p1,l); alpha = (double)l; av2 = avma; while (n) { if (n < CBRTVERYBIGINT) /* p3 = n1(n1-2)(n1-4) / n^3 */ p3 = divru(mulur(n1-4,mulur(n1*(n1-2),p1)),n*n*n); else { if (n1 < SQRTVERYBIGINT) p3 = divru(divru(mulur(n1-4,mulur(n1*(n1-2),p1)),n*n),n); else p3 = divru(divru(divru(mulur(n1-4,mulur(n1,mulur(n1-2,p1))),n),n),n); } p3 = divru(divru(p3,100100025), 327843840); subisz(p2,k1,p2); subirz(p2,p3,p1); alpha += alpha2; l = (long)(1+alpha); /* new mantissa length */ if (l > prec) l = prec; setlg(p1,l); avma = av2; n--; n1-=6; } p1 = divur(53360,p1); return gerepileuptoleaf(av, mulrr(p1,sqrtr_abs(stor(k3,prec)))); } #endif /* Gauss - Brent-Salamin AGM iteration */ GEN constpi(long prec) { GEN A, B, C, tmppi; long i, G; pari_sp av, av2; if (gpi && lg(gpi) >= prec) return gpi; av = avma; tmppi = newblock(prec); *tmppi = evaltyp(t_REAL) | evallg(prec); G = - bit_accuracy(prec); prec++; A = real_1(prec); i = A[1]; A[1] = evalsigne(1) | _evalexpo(-1); B = sqrtr_abs(A); /* = 1/sqrt(2) */ A[1] = i; 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); setexpo(a, expo(a)-1); b = mulrr(A,B); affrr(a, A); affrr(sqrtr_abs(b), B); avma = av3; y = sqrr(B_A); setexpo(y, expo(y) + i - 2); affrr(subrr(C, y), C); avma = av2; } setexpo(C, expo(C)+2); affrr(divrr(sqrr(addrr(A,B)), C), tmppi); if (gpi) gunclone(gpi); avma = av; return gpi = tmppi; } GEN mppi(long prec) { return rtor(constpi(prec), prec); } /* Pi * 2^n */ GEN Pi2n(long n, long prec) { GEN x = mppi(prec); setexpo(x, 1+n); return x; } /* I * Pi * 2^n */ GEN PiI2n(long n, long prec) { GEN z = cgetg(3,t_COMPLEX); gel(z,1) = gen_0; gel(z,2) = Pi2n(n, prec); return z; } /* 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 && lg(geuler) >= prec) return geuler; av1 = avma; tmpeuler = newblock(prec); *tmpeuler = evaltyp(t_REAL) | evallg(prec); prec++; l = prec+1; x = (long) (1 + bit_accuracy_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? real_0_bit(e): real_1(nbits2prec(-e)); } static GEN powr0(GEN x) { long lx = lg(x); return (lx == 2 || !signe(x)) ? mpexp0(x): real_1(lx); } /* 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) = RgX_get_1(gel(x,1)); return y; case t_RFRAC: return RgX_get_1(gel(x,2)); case t_POL: case t_SER: return RgX_get_1(x); case t_MAT: lx=lg(x); if (lx==1) return cgetg(1,t_MAT); if (lx != lg(x[1])) pari_err(mattype1,"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 */ if (a[2] == 1) return (s>0)? gen_1: gen_m1; if (a[2] == 2) { a = int2u(N); setsigne(a,s); return a; } } if (N == 1) { a = icopy(a); setsigne(a,s); return a; } if (N == 2) return sqri(a); av = avma; y = gen_powu(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 x, long n) { long sx, s; GEN t, y; if (!n) return gen_1; sx = signe(x); if (!sx) { if (n < 0) pari_err(gdiver); return gen_0; } s = (sx < 0 && odd(n))? -1: 1; if (n > 0) return powiu_sign(x, n, s); t = (s > 0)? gen_1: gen_m1; if (is_pm1(x)) return t; /* n < 0, |x| > 1 */ y = cgetg(3,t_FRAC); gel(y,1) = t; gel(y,2) = powiu_sign(x, -n, 1); /* force denominator > 0 */ return y; } GEN powuu(ulong p, ulong N) { long P[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0}; if (!N) return gen_1; if (!p) return gen_0; P[2] = p; return powiu_sign(P, N, 1); } /* assume p^k is SMALL */ ulong upowuu(ulong p, ulong k) { ulong i, pk; if (!k) return 1; if (p == 2) return 1UL<= 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; sr_muldata D; if (a == 1) return real_1(prec); if (a == 2) return real2n(n, prec); if (n == 1) return stor(a, prec); av = avma; D.sqr = &sqri; D.mulug = &mului; D.prec = prec; D.a = (long)a; y = leftright_pow_u_fold(utoipos(a), n, (void*)&D, &_rpowuu_sqr, &_rpowuu_msqr); if (typ(y) == t_INT) y = itor(y, prec); return gerepileuptoleaf(av, y); } GEN powrs(GEN x, long n) { pari_sp av = avma; GEN y; if (!n) return powr0(x); y = gen_powu(x, (ulong)labs(n), NULL, &_sqrr, &_mulr); if (n < 0) y = invr(y); return gerepileupto(av,y); } GEN powru(GEN x, ulong n) { if (!n) return powr0(x); return gen_powu(x, n, NULL, &_sqrr, &_mulr); } /* 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(talker,"degree overflow in pow_monome"); 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(x[4])) { if (n < 0) pari_err(gdiver); 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(overflower,"valp()"); if (!signe(x[4])) { if (signe(n) < 0) pari_err(gdiver); 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 sx = signe(a), s; if (!sx) { if (n < 0) pari_err(gdiver); return gen_0; } s = (sx < 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(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(overflower,"lg()"); if (signe(n) < 0) pari_err(gdiver); return gen_0; case t_FRAC: pari_err(overflower,"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); } } } /* 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) { pari_sp av, tetpil; GEN y, p1, p2, lead; if (varncmp(gvar(n), varn(x)) <= 0) return gexp(gmul(n, glog(x,prec)), prec); lead = gel(x,2); if (gequal1(lead)) { GEN X, Y, alp = gadd(n,gen_1); /* will be left on the stack */ long lx, mi, i, j, d; lx = lg(x); y = cgetg(lx,t_SER); y[1] = evalsigne(1) | _evalvalp(0) | evalvarn(varn(x)); X = x+2; Y = y+2; d = mi = lx-3; while (mi>=1 && isrationalzero(gel(X,mi))) mi--; gel(Y,0) = gen_1; for (i=1; i<=d; i++) { av = avma; p1 = gen_0; for (j=1; j<=minss(i,mi); j++) { p2 = gsubgs(gmulgs(alp,j),i); p1 = gadd(p1, gmul(gmul(p2,gel(X,j)),gel(Y,i-j))); } tetpil = avma; gel(Y,i) = gerepile(av,tetpil, gdivgs(p1,i)); } return y; } p1 = gdiv(x,lead); if (typ(p1) != t_SER) pari_err(typeer, "ser_pow"); gel(p1,2) = gen_1; /* in case it's inexact */ if (typ(n) == t_FRAC && !isinexact(lead) && ispower(lead, gel(n,2), &p2)) p2 = powgi(p2, gel(n,1)); else p2 = gpow(lead,n, prec); return gmul(p2, gpow(p1, n, prec)); } static long val_from_i(GEN E) { if (is_bigint(E)) pari_err(talker,"valuation overflow in sqrtn"); return itos(E); } /* return x^q, assume typ(x) = t_SER, typ(q) = t_FRAC and q != 0 */ static GEN ser_powfrac(GEN x, GEN q, long prec) { long e = valp(x); GEN y, E = gmulsg(e, q); if (!signe(x)) return zeroser(varn(x), val_from_i(gfloor(E))); if (typ(E) != t_INT) pari_err(talker,"%Ps should divide valuation (= %ld) in sqrtn",q[2], e); e = val_from_i(E); y = leafcopy(x); setvalp(y, 0); y = ser_pow(y, q, prec); if (typ(y) == t_SER) /* generic case */ y[1] = evalsigne(1) | evalvalp(e) | evalvarn(varn(x)); else /* e.g coeffs are POLMODs */ y = gmul(y, monomial(gen_1, e, varn(x))); return y; } GEN gpow(GEN x, GEN n, long prec) { long i, lx, tx, tn = typ(n); pari_sp av; GEN y; if (tn == t_INT) return powgi(x,n); tx = typ(x); if (is_matvec_t(tx)) { y = cgetg_copy(x, &lx); for (i=1; i= HIGHEXPOBIT) pari_err(talker,"gpow: underflow or overflow"); avma = av; return real_0_bit(itos(x)); } if (tn == t_FRAC) { GEN z, d = gel(n,2), a = gel(n,1); switch (tx) { case t_INTMOD: if (!BPSW_psp(gel(x,1))) pari_err(talker,"gpow: modulus %Ps is not prime",x[1]); y = cgetg(3,t_INTMOD); gel(y,1) = icopy(gel(x,1)); av = avma; z = Fp_sqrtn(gel(x,2), d, gel(x,1), NULL); if (!z) pari_err(talker,"gpow: nth-root does not exist"); gel(y,2) = gerepileuptoint(av, Fp_pow(z, a, gel(x,1))); return y; case t_PADIC: z = equaliu(d, 2)? Qp_sqrt(x): Qp_sqrtn(x, d, NULL); if (!z) pari_err(talker, "gpow: nth-root does not exist"); return gerepileupto(av, powgi(z, a)); case t_FFELT: return gerepileupto(av,FF_pow(FF_sqrtn(x,d,NULL),a)); } } i = (long) precision(n); if (i) prec=i; y = gmul(n, glog(x,prec)); return gerepileupto(av, gexp(y,prec)); } /********************************************************************/ /** **/ /** RACINE CARREE **/ /** **/ /********************************************************************/ /* assume x unit, precp(x) = pp > 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)); } } /* x unit defined modulo p^e, e > 0 */ static int Up_issquare(GEN x, GEN p, long e) { if (equaliu(p,2)) { 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; } return kronecker(x,p)==1; } 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) pari_err(talker,"odd exponent in p-adic sqrt"); y = cgetg(5,t_PADIC); pp = precp(x); mod = gel(x,3); x = gel(x,4); /* lift to t_INT */ e >>= 1; z = Up_sqrt(x, p, pp); if (!z) pari_err(sqrter5); 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(typeer, "Zn_sqrt"); if (typ(fn) == t_INT) fn = Z_factor(absi(fn)); else if (!is_Z_factor(fn)) pari_err(typeer, "Zn_sqrt"); np = lg(gel(fn, 1))-1; 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); } long Zn_issquare(GEN d, GEN fn) { long j, np; if (typ(d) != t_INT) pari_err(typeer, "Zn_issquare"); if (typ(fn) == t_INT) fn = Z_factor(absi(fn)); else if (!is_Z_factor(fn)) pari_err(typeer, "Zn_issquare"); np = lg(gel(fn, 1))-1; 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) { if (odd(v)) return 0; if (!Up_issquare(r, p, e-v)) return 0; } } return 1; } static GEN sqrt_ser(GEN b, long prec) { long e = valp(b), vx = varn(b), lx, lold, j; ulong mask; GEN a, x; if (!signe(b)) return zeroser(vx, e>>1); a = leafcopy(b); x = cgetg_copy(b, &lx); if (e & 1) pari_err(talker,"2 should divide valuation (= %ld) in sqrtn",e); a[1] = x[1] = evalsigne(1) | evalvarn(0) | _evalvalp(0); if (gissquareall(gel(a,2), &gel(x,2)) == gen_0) gel(x,2) = gsqrt(gel(a,2), prec); 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++) x[j] = 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, p1; switch(typ(x)) { case t_REAL: return sqrtr(x); case t_INTMOD: y = cgetg(3,t_INTMOD); gel(y,1) = icopy(gel(x,1)); p1 = Fp_sqrt(gel(x,2),gel(y,1)); if (!p1) pari_err(sqrter5); gel(y,2) = p1; 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), u, v; if (isrationalzero(b)) return gsqrt(a, prec); y = cgetg(3,t_COMPLEX); av = avma; p1 = cxnorm(x); if (typ(p1) == t_INTMOD) pari_err(impl,"sqrt(complex of t_INTMODs)"); p1 = gsqrt(p1, prec); /* t_REAL */ if (!signe(p1)) u = v = gerepileuptoleaf(av, sqrtr(p1)); else if (gsigne(a) < 0) { p1 = sqrtr( gmul2n(gsub(p1,a), -1) ); if (gsigne(b) < 0) togglesign(p1); v = gerepileuptoleaf(av, p1); av = avma; if (!signe(p1)) /* possible if a = 0 */ u = v; else u = gerepileuptoleaf(av, gdiv(b, shiftr(v,1))); } else { p1 = sqrtr( gmul2n(gadd(p1,a), -1) ); u = gerepileuptoleaf(av, p1); av = avma; if (!signe(p1)) /* possible if a = 0 */ v = u; else v = gerepileuptoleaf(av, gdiv(b, shiftr(u,1))); } gel(y,1) = u; gel(y,2) = v; return y; } case t_PADIC: return Qp_sqrt(x); case t_FFELT: return FF_sqrt(x); default: av = avma; if (!(y = toser_i(x))) break; return gerepilecopy(av, sqrt_ser(y, prec)); } return transc(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 (lgefint(n)==3 && n[2]==2) return stor(-1, prec); return gerepileupto(av, exp_Ir( divri(Pi2n(1, prec), n) )); } /*Only the O() of y is used*/ GEN rootsof1padic(GEN n, GEN y) { pari_sp av0 = avma, av; GEN z, r = cgetp(y); av = avma; (void)Fp_sqrtn(gen_1,n,gel(y,2),&z); if (z==gen_0) { avma = av0; return gen_0; }/*should not happen*/ z = Zp_sqrtnlift(gen_1, n, z, gel(y,2), 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(talker, "error in p-adic log, %Ps is not a prime", p); pari_err(bugparier, "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(talker,"zero argument in Qp_log"); 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 = avma, tetpil; GEN q, p = gel(x,2); long e; if (!signe(x[4])) { 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 && lgefint(p)==3 && p[2]==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 && lgefint(p)==3 && p[2]==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 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(talker,"second arg must be integer in gsqrtn"); if (!signe(n)) pari_err(talker,"1/0 exponent in gsqrtn"); 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) /*speed-up since there is no way to call rootsof1complex from gp*/ y = real_1(prec); else if (gequal0(x)) { if (signe(n) < 0) pari_err(gdiver); if (isinexactreal(x)) { long e = gexpo(x), junk; y = real_0_bit(e < 2? 0: sdivsi_rem(e, n, &junk)); } else y = real_0(prec); } else y = gerepileupto(av, gexp(gdiv(glog(x,prec), n), prec)); if (zetan) *zetan = rootsof1complex(n,prec); return y; case t_QUAD: return gsqrtn(quadtofp(x, prec), n, zetan, prec); default: av = avma; if (!(y = toser_i(x))) break; return gerepileupto(av, ser_powfrac(y, ginv(n), prec)); } pari_err(typeer,"gsqrtn"); return NULL;/* not reached */ } /********************************************************************/ /** **/ /** EXP(X) - 1 **/ /** **/ /********************************************************************/ /* exp(|x|) - 1, assume x != 0. * For efficiency, x should be reduced mod log(2): if so, we have a < 0 */ GEN exp1r_abs(GEN x) { long l = lg(x), a = expo(x), b = bit_accuracy(l), L, i, n, m, e, B; GEN y, p2, X; pari_sp av; double d; if (b + a <= 0) return mpabs(x); y = cgetr(l); av = avma; B = b/3 + BITS_IN_LONG + (BITS_IN_LONG*BITS_IN_LONG)/ b; d = a/2.; m = (long)(d + sqrt(d*d + B)); /* >= 0 */ if (m < (-a) * 0.1) m = 0; /* not worth it */ L = l + nbits2nlong(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; e = m - a; /* >= 1 */ /* ~ -1/log(2) - log_2 Y */ d = e+BITS_IN_LONG-1-1/LOG2 - log2((double)(ulong)x[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); X[1] = evalsigne(1) | evalexpo(-e); 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; setlg(X,l1); p3 = divru(X,i); l1 += dvmdsBIL(s - expo(p3), &s); if (l1>L) l1=L; setlg(unr,l1); p1 = addrr_sign(unr,1, i == n? p3: mulrr(p3,p2),1); setlg(p2,l1); affrr(p1,p2); /* p2 <- 1 + (X/i)*p2 */ } setlg(X,L); p2 = mulrr(X,p2); } for (i=1; i<=m; i++) { if (lg(p2) > L) setlg(p2,L); p2 = mulrr(p2, addsr(2,p2)); } affrr_fixlg(p2,y); avma = av; return y; } GEN mpexp1(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)); } /********************************************************************/ /** **/ /** 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(overflower, "expo()"); /* avoid overflow in q */ if (d < 0) q = -q; *sh = q; if (q) { long l = lg(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 = lg(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) { setexpo(z, expo(z)+sh); if (lg(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-bit_accuracy(minss(l,lg(t)))) pari_err(talker,""); } #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 = lg(x), sh; GEN a, t, z; ulong mask; if (l <= maxss(EXPNEWTON_LIMIT, (1L<>= 1; } a = mpexp_basecase(rtor(x, p+2)); x = addrs(x,1); if (lg(x) < l+1) x = rtor(x, l+1); a = rtor(a, l+1); /*append 0s */ t = NULL; for(;;) { p <<= 1; if (mask & 1) p--; mask >>= 1; setlg(x, p+2); setlg(a, p+2); 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) setexpo(z, expo(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(talker,"p-adic argument out of range in gexp"); 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 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, 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; } static GEN serexp(GEN x, long prec) { pari_sp av; long i,j,lx,ly,ex,mi; GEN p1,y,xd,yd; ex = valp(x); if (ex < 0) pari_err(negexper,"gexp"); if (gequal0(x)) return gaddsg(1,x); lx = lg(x); if (ex) { ly = lx+ex; y = cgetg(ly,t_SER); mi = lx-1; while (mi>=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 = lg(x), L = 5-bit_accuracy(l); GEN a1, b1, y = cgetr(l); pari_sp av = avma; a1 = addrr(real_1(l), x); setexpo(a1, expo(a1)-1); b1 = sqrtr_abs(x); while (agmr_gap(a1,b1,L)) { GEN a = a1; a1 = addrr(a,b1); setexpo(a1, expo(a1)-1); b1 = sqrtr_abs(mulrr(a,b1)); } affrr_fixlg(a1,y); avma = av; return y; } static int agmcx_gap(GEN a, GEN b, long L) { GEN d = gsub(b, a); return (!gequal0(d) && gexpo(d) - gexpo(b) >= L); } static GEN agm1cx(GEN x, long prec) { GEN a1, b1; pari_sp av = avma, av2; long L, l = precision(x); if (!l) l = prec; L = 5-bit_accuracy(l); a1 = gtofp(gmul2n(gadd(real_1(l), x), -1), l); /* avoid loss of accuracy */ av2 = avma; b1 = gsqrt(x, prec); while (agmcx_gap(a1,b1,L)) { GEN a = a1; a1 = gmul2n(gadd(a,b1),-1); av2 = avma; b1 = gsqrt(gmul(a,b1), prec); } avma = av2; return gerepileupto(av,a1); } /* agm(1,x) */ static GEN agm1(GEN x, long prec) { GEN p1, a, 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)) && gsigne(gel(x,1)) > 0) return agm1(gel(x,1), prec); return agm1cx(x, prec); case t_PADIC: av = avma; a1 = x; b1 = gen_1; l = precp(x); do { a = a1; a1 = gmul2n(gadd(a,b1),-1); b1 = Qp_sqrt(gmul(a,b1)); 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 transc(agm1,x,prec); } GEN agm(GEN x, GEN y, long prec) { long ty = typ(y); pari_sp av; if (is_matvec_t(ty)) { ty = typ(x); if (is_matvec_t(ty)) pari_err(talker,"agm of two vector/matrices"); swap(x, y); } if (gequal0(y)) return gcopy(y); av = avma; return gerepileupto(av, gmul(y, agm1(gdiv(x,y), prec))); } /********************************************************************/ /** **/ /** LOG(X) **/ /** **/ /********************************************************************/ /* cf logagmr_abs(). Compute Pi/2agm(1, 4/2^n) ~ log(2^n) = n log(2) */ GEN constlog2(long prec) { pari_sp av; long l, n; GEN y, tmplog2; if (glog2 && lg(glog2) >= prec) return glog2; tmplog2 = newblock(prec); *tmplog2 = evaltyp(t_REAL) | evallg(prec); av = avma; l = prec+1; n = bit_accuracy(l) >> 1; y = divrr(Pi2n(-1, prec), agm1r_abs( real2n(2 - n, l) )); affrr(divru(y,n), tmplog2); if (glog2) gunclone(glog2); avma = av; return glog2 = tmplog2; } GEN mplog2(long prec) { return rtor(constlog2(prec), prec); } static GEN logagmr_abs(GEN q) { long prec = lg(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; prec++; lim = bit_accuracy(prec) >> 1; Q = rtor(q,prec); Q[1] = evalsigne(1) | evalexpo(lim); _4ovQ = invr(Q); setexpo(_4ovQ, expo(_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 = lg(X); GEN z, x, y; ulong u; int neg; 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; } neg = 1; } else { /* choose x - 1 */ u &= ~HIGHBIT; /* u - HIGHBIT, assuming HIGHBIT set */ while (!u && ++k < l) u = (ulong)X[k]; neg = 0; } if (k == l) return EX? mulsr(EX, mplog2(l)): real_0(l); z = cgetr(EX? l: l - (k-2)); ltop = avma; a = bit_accuracy(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 = bit_accuracy(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 += divsBIL(m); x = rtor(X,L); if (neg) x[1] = evalsigne(1) | _evalexpo(-1); else x[1] = evalsigne(1) | _evalexpo(0); /* 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 = lg(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^(-bit_accuracy(L)), hence * n+1 > bit_accuracy(L) /-log_2(y^2) */ d = -2*dbllog2r(y); /* ~ -log_2(y^2) */ k = (long)(2*(bit_accuracy(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; setlg(S, l1); setlg(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 */ setlg(y2, l1); T = mulrr(S,y2); if (k == 1) break; l1 += dvmdsBIL(s + incs, &s); if (l1>L) l1=L; setlg(S, l1); setlg(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 */ } setexpo(y, expo(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 */ GEN logagmcx(GEN q, long prec) { GEN z, y, Q, a, b; long lim, e, ea, eb; pari_sp av; int neg = 0; e = precision(q); if (e > prec) prec = e; z = cgetc(prec); av = avma; prec++; if (gsigne(gel(q,1)) < 0) { q = gneg(q); neg = 1; } lim = bit_accuracy(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); if (ea <= eb) { setexpo(Q[1], lim - eb + ea); setexpo(Q[2], lim); e = lim - eb; } else { setexpo(Q[1], lim); setexpo(Q[2], lim - ea + eb); e = lim - ea; } /* 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 (lg(a) == 3) 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(talker,"non positive argument in mplog"); return logr_abs(x); } GEN teich(GEN x) { GEN p,q,y,z,aux,p1; long n, k; pari_sp av; if (typ(x)!=t_PADIC) pari_err(talker,"not a p-adic argument in teichmuller"); if (!signe(x[4])) return gcopy(x); p = gel(x,2); q = gel(x,3); z = gel(x,4); y = cgetp(x); av = avma; if (equaliu(p,2)) z = (mod4(z) & 2)? addsi(-1,q): gen_1; else { p1 = addsi(-1, p); z = remii(z, p); aux = diviiexact(addsi(-1,q),p1); n = precp(x); for (k=1; k= 0) { if (!signe(x)) pari_err(talker,"zero argument in mplog"); return logr_abs(x); } y = cgetg(3,t_COMPLEX); gel(y,1) = logr_abs(x); gel(y,2) = mppi(lg(x)); return y; case t_COMPLEX: if (ismpzero(gel(x,2))) return glog(gel(x,1), prec); 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); case t_INTMOD: pari_err(typeer,"glog"); default: av = avma; if (!(y = toser_i(x))) break; if (valp(y) || gequal0(y)) pari_err(talker,"log is not meromorphic at 0"); p1 = integ(gdiv(derivser(y), y), varn(y)); /* log(y)' = y'/y */ if (!gequal1(gel(y,2))) p1 = gadd(p1, glog(gel(y,2),prec)); return gerepileupto(av, p1); } return transc(glog,x,prec); } /********************************************************************/ /** **/ /** SINE, COSINE **/ /** **/ /********************************************************************/ /* Reduce x0 mod Pi/2 to x in [-Pi/4, Pi/4]. Return cos(x)-1 */ static GEN mpsc1(GEN x, long *ptmod8) { long a = expo(x), b, l, L, i, n, m, e, B; GEN y, p2, x2; double d; n = 0; if (a >= 0) { GEN q; if (a > 30) { GEN z, pitemp = mppi(nbits2prec(a + 32)); setexpo(pitemp,-1); z = addrr(x,pitemp); /* = x + Pi/4 */ if (expo(z) >= bit_accuracy(lg(z)) + 3) pari_err(precer,"mpsc1"); setexpo(pitemp, 0); q = floorr( divrr(z,pitemp) ); /* round ( x / (Pi/2) ) */ } else { q = stoi((long)floor(rtodbl(x) / (PI/2) + 0.5)); } if (signe(q)) { x = subrr(x, mulir(q, Pi2n(-1, lg(x)+1))); /* x mod Pi/2 */ a = expo(x); if (!signe(x) && a >= 0) pari_err(precer,"mpsc1"); n = mod4(q); if (n && signe(q) < 0) n = 4 - n; } } /* a < 0 */ l = lg(x); b = signe(x); *ptmod8 = (b < 0)? 4 + n: n; if (!b) return real_0_bit((expo(x)<<1) - 1); b = bit_accuracy(l); if (b + (a<<1) <= 0) { y = sqrr(x); y[1] = evalsigne(-1)|evalexpo(expo(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 + nbits2nlong(m); b += m; e = m - a; /* >= 1 */ /* ~ 2( -1/log(2) - log_2 Y ) */ d = 2.0 * (e+BITS_IN_LONG-1-1/LOG2 - log2((double)(ulong)x[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); x[1] = evalsigne(1) | evalexpo(-e); x2 = sqrr(x); if (n == 1) p2 = x2; 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; setlg(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); setlg(unr,l1); p1 = addrr_sign(unr,1, p1,-signe(p1)); setlg(p2,l1); affrr(p1,p2); avma = av; } p2[1] = evalsigne(-signe(p2)) | evalexpo(expo(p2)-1); /* p2 := -p2/2 */ setlg(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)); setexpo(p2, expo(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 < 3) l = 3; return real_1(l); } av = avma; p1 = mpsc1(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 gch(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_INTMOD: pari_err(typeer,"gcos"); case t_PADIC: x = cos_p(x); if (!x) pari_err(talker,"p-adic argument out of range in gcos"); return x; default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepileupto(av, gaddsg(1,y)); if (valp(y) < 0) pari_err(negexper,"gcos"); gsincos(y,&u,&v,prec); return gerepilecopy(av,v); } return transc(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 = mpsc1(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))) { GEN z = cgetg(3, t_COMPLEX); gel(z,1) = gen_0; gel(z,2) = gsh(gel(x,2),prec); return z; } 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_INTMOD: pari_err(typeer,"gsin"); case t_PADIC: x = sin_p(x); if (!x) pari_err(talker,"p-adic argument out of range in gsin"); return x; default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepilecopy(av, y); if (valp(y) < 0) pari_err(negexper,"gsin"); gsincos(y,&u,&v,prec); return gerepilecopy(av,u); } return transc(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=mpsc1(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); } /* return exp(ix), x a t_REAL */ GEN exp_Ir(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; } void gsincos(GEN x, GEN *s, GEN *c, long prec) { long ii, 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(talker,"non zero exponent in gsincos"); 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) { p1 = leafcopy(y); gel(p1,2) = gen_0; gsincos(normalize(p1),&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 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(talker, "l <= 2 in RgX_to_ser"); 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(typeer,"gtolong"); 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(x[1])!=t_REAL || typ(x[2])!=t_REAL) return 0; return (expo(x[1])>expo(x[2])); } if (gequal0(gel(x,2))) { if (typ(x[1])!=t_REAL || typ(x[2])!=t_REAL) return 0; return (expo(x[2])>expo(x[1])); } return 0; case t_PADIC: return !signe(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 != lg(gel(x,1))) 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 is_pm1(x) && signe(x)==1; 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 is_pm1(x) && signe(x)== -1; 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 gcmpX(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]); } } /* 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), f; pari_sp av; if (is_intreal_t(tx)) { if (is_intreal_t(ty)) return mpcmp(x,y); } else { if (tx==t_STR) { if (ty != t_STR) return 1; return cmp_str(GSTR(x), GSTR(y)); } if (tx != t_FRAC) { if (ty == t_STR) return -1; pari_err(typeer,"comparison"); } } if (ty == t_STR) return -1; if (!is_intreal_t(ty) && ty != t_FRAC) pari_err(typeer,"comparison"); av=avma; f = gsigne( gsub(x,y) ); avma=av; return f; } 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(typeer,"comparison"); return 0; /* not reached */ } static int lexcmp_scal_vec(GEN x, GEN y) { long fl; if (lg(y)==1) return 1; fl = lexcmp(x,gel(y,1)); if (fl) return fl; return -1; } static int lexcmp_vec_mat(GEN x, GEN y) { if (lg(x)==1) return -1; return lexcmp_scal_vec(x,y); } /* as gcmp for vector/matrices, using lexicographic ordering on components */ int lexcmp(GEN x, GEN y) { const long tx=typ(x), ty=typ(y); long lx,ly,l,fl,i; if (!is_matvec_t(tx)) { if (!is_matvec_t(ty)) return gcmp(x,y); return lexcmp_scal_vec(x,y); } if (!is_matvec_t(ty)) return -lexcmp_scal_vec(y,x); /* x and y are matvec_t */ if (ty==t_MAT) { if (tx != t_MAT) return lexcmp_vec_mat(x,y); } else if (tx==t_MAT) return -lexcmp_vec_mat(y,x); /* tx = ty = t_MAT, or x and y are both vect_t */ lx = lg(x); ly = lg(y); l = minss(lx,ly); for (i=1; i= 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; } /* 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; CATCH(CATCH_ALL) { CATCH_RELEASE(); switch(pari_errno) { case errpile: case memer: pari_err(pari_errno); case alarmer: pari_err(pari_errno, global_err_data); } return 0; } TRY { i = gequal0(gadd(x, gneg_i(y))); } 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_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 first) { long i,k, val = LONG_MAX, lx = lg(x); for (i=first; i1) pari_warn(warnmem,"ggval"); x = gerepilecopy(av, x); } } } if (varncmp(vx, vp) > 0) return 0; } else if (tp != t_INT) break; i=2; while (isrationalzero(gel(x,i))) i++; return minval(x,p,i); case t_SER: if (tp!=t_POL && tp!=t_SER && tp!=t_INT) break; vp = gvar(p); vx = varn(x); if (vp == vx) { vp = RgX_val(p); if (!vp) pari_err(talker, "forbidden divisor %Ps in ggval", p); return (long)(valp(x) / vp); } if (varncmp(vx, vp) > 0) return 0; return minval(x,p,2); case t_RFRAC: return ggval(gel(x,1),p) - ggval(gel(x,2),p); case t_COMPLEX: case t_QUAD: case t_VEC: case t_COL: case t_MAT: return minval(x,p,1); } pari_err(talker,"forbidden or conflicting type in gval"); 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(talker, "p = 1 in Z_lvalrem"); 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(talker, "p = 1 in Z_lvalrem"); 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), assign 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 = 0; ulong r; GEN N, q; if (lgefint(n) == 3) return u_lvalrem_stop((ulong*)&n[2], p, stop); av = avma; q = diviu_rem(n, p, &r); if (!r) { 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); affii(N, n); } *stop = isless_iu(q,p); avma = av; 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(talker, "p = 1 in gen_pvalrem"); 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); } static long gen_2valrem(GEN x, GEN *px, long imin) { long i, lx = lg(x), v = LONG_MAX; GEN z; 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) { *px = x; return 0; } /* early abort */ } } z = cgetg_copy(x, &lx); z[1] = x[1]; for (i=imin; 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); } GEN vecmax(GEN x) { long lx = lg(x), i, j; GEN s; if (lx==1) pari_err(talker, "empty vector in vecmax"); switch(typ(x)) { case t_VEC: case t_COL: s = gel(x,1); for (i=2; i 0) s = gel(x,i); return gcopy(s); case t_MAT: { long lx2 = lg(x[1]); if (lx2==1) pari_err(talker, "empty vector in vecmax"); s = gcoeff(x,1,1); i = 2; for (j=1; j 0) s = gel(c,i); } return gcopy(s); } case t_VECSMALL: return stoi(vecsmall_max(x)); default: return gcopy(x); } } GEN vecmin(GEN x) { long lx = lg(x), i, j; GEN s; if (lx==1) pari_err(talker, "empty vector in vecmin"); switch(typ(x)) { case t_VEC: case t_COL: s = gel(x,1); for (i=2; i GEN */ /* affect long s to GEN x. Useful for initialization. */ /* */ /*******************************************************************/ static void padicaff0(GEN x) { if (signe(x[4])) { setvalp(x, valp(x)|precp(x)); affsi(0,gel(x,4)); } } void gaffsg(long s, GEN x) { switch(typ(x)) { case t_INT: affsi(s,x); break; case t_REAL: affsr(s,x); break; case t_INTMOD: modsiz(s,gel(x,1),gel(x,2)); break; case t_FRAC: affsi(s,gel(x,1)); affsi(1,gel(x,2)); break; case t_COMPLEX: gaffsg(s,gel(x,1)); gaffsg(0,gel(x,2)); break; case t_PADIC: { long vx; GEN y; if (!s) { padicaff0(x); break; } vx = Z_pvalrem(stoi(s), gel(x,2), &y); setvalp(x,vx); modiiz(y,gel(x,3),gel(x,4)); break; } case t_QUAD: gaffsg(s,gel(x,2)); gaffsg(0,gel(x,3)); break; default: pari_err(operf,"",stoi(s),x); } } /*******************************************************************/ /* */ /* GENERIC AFFECTATION */ /* Affect the content of x to y, whenever possible */ /* */ /*******************************************************************/ /* x PADIC, Y INT, return lift(x * Mod(1,Y)) */ GEN padic_to_Fp(GEN x, GEN Y) { pari_sp av = avma; GEN p = gel(x,2), z; long vy, vx = valp(x); if (!signe(Y)) pari_err(gdiver); vy = Z_pvalrem(Y,p, &z); if (vx < 0 || !gequal1(z)) pari_err(operi,"",x, mkintmod(gen_1,Y)); if (vx >= vy) { avma = av; return gen_0; } z = gel(x,4); if (!signe(z) || vy > vx + precp(x)) pari_err(operi,"",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(operi,"",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(operi,"",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) { pari_err(talker,"trying to overwrite a universal object in gaffect (%s)", s); } 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(operi,"",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(operi,"",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(operi,"",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(operi,"",x,y); 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 < 3) prec = 3; 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)); setexpo(z, expo(z)-1); } else { z = sqrtr_abs(z); setexpo(z, expo(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 = gmul2n(gsub(Qp_sqrt(cvtop(D,p,d)), 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 - ggval(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(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(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(typeer,"cvtop2"); 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(talker,"not an integer modulus in cvtop"); 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(typeer,"cvtop"); 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(typeer,"gexpo"); 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); GEN y, z; if (typ(x) != t_SER) pari_err(typeer,"normalize"); 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(x[1]); } pari_err(typeer,"gsigne"); 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(talker, "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(typeer,"listkill"); 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(typeer,"listinsert"); z = list_data(L); l = z? lg(z): 1; if (index <= 0 || index > l) pari_err(talker,"bad index in listinsert"); ensure_nb(L, l); z = list_data(L); for (i=l; i > index; i--) z[i] = 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(typeer,"listinsert"); if (index < 0) pari_err(talker,"negative index (%ld) in listpop", index); z = list_data(L); if (!z) pari_err(talker,"empty list in listpop"); l = lg(z)-1; if (!l) pari_err(talker,"empty list in listpop"); 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(typeer,"listsort"); v = list_data(L); l = v? lg(v): 1; if (l < 3) return; if (flag) { long lnew; perm = gen_indexsort_uniq(L, (void*)&lexcmp, cmp_nodata); lnew = lg(perm); /* may have changed since 'uniq' */ vnew = cgetg(lnew,t_VEC); for (i=1; i 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). tau = pr[5] or (more efficient) mult. table for pr[5] */ static long fast_val(GEN nf,GEN L0,GEN cx,GEN pr,GEN tau) { pari_sp av = avma; GEN p = pr_get_p(pr); long v = typ(L0) == t_INT? 0: int_elt_val(nf,L0,p,tau,NULL); if (cx) { long w = Q_pval(cx, p); 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, vectau; 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); vectau = 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 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 shallowconcat(D, diagonal_shallow(cyc)); } 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 = Idealstar(nf,module, nf_GEN|nf_INIT); cycbid = bid_get_cyc(bid); genbid = bid_get_gen_nocheck(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) */ H = ZM_hnfall( get_dataunit(bnf, bid), do_init? &u: NULL, 1); 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(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++) { u1[j]=u[j]; setlg(u[j],RU+1); } u += RU; for (j=1; j<=Ri; j++) { u2[j]=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(flagerr,"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 */ return gerepileuptoint(av, mulii(h, ZM_det_triangular(ZM_hnf(D)))); } 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(El[i]) != t_INT && signe(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(bugparier,"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 = absi(nf_get_disc(nf)); fa = gel(Z_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)); } /* x given by its embeddings */ GEN norm_by_embed(long r1, GEN x) { long ru = lg(x)-1, i = ru-1; GEN p = gel(x,ru); if (r1 != ru) { p = gnorm(p); for (; i>r1; i--) p = gmul(p, gnorm(gel(x,i))); } for (; i>0; i--) p = gmul(p, gel(x,i)); return p; } static int is_unit(GEN M, long r1, GEN x) { pari_sp av = avma; GEN Nx = ground( norm_by_embed(r1, RgM_zc_mul(M,x)) ); 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, i, j, k, s, *x, r1, 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(); } r1 = nf_get_r1(nf); n = nf_get_degree(nf); minim_alloc(n+1, &q, &x, &y, &z, &v); M = gprec_w(nf_get_M(nf), prec); r = Q_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(gach(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 ]: %Ps\n",n1,n2,n3,gprec_w(M0_pro,3)); 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 ]: %Ps\n",n1,n2,n3,gprec_w(M0_pro,3)); 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 ]: %Ps\n",n1,n2,n3,gprec_w(M0_pro,3)); 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 N,R1,R2,RU,i; GEN nf,M0,M,G,bound,minunit,newminunit; GEN vecminim,p1,pol,y; nf = bnf_get_nf(bnf); N = nf_get_degree(nf); nf_get_sign(nf, &R1, &R2); RU = R1+R2-1; if (!RU) return gen_1; G = nf_get_G(nf); minunit = gnorml2(RgM_RgC_mul(G, gel(units,1))); /* T2(units[1]) */ for (i=2; i<=RU; i++) { newminunit = gnorml2(RgM_RgC_mul(G, gel(units,i))); if (gcmp(newminunit,minunit) < 0) minunit = newminunit; } 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); if (DEBUGLEVEL>2) { pol = gaddgs(gsub(monomial(gen_1,N,0),monomial(bound,1,0)),N-1); p1 = roots(pol,DEFAULTPREC); y= real_i(gel(p1, 2 + (N&1))); M0 = gmul2n(gmulsg(N*(N-1),sqrr(glog(y,DEFAULTPREC))),-2); err_printf("pol = %Ps\n",pol); err_printf("old method: y = %Ps, M0 = %Ps\n",y,gprec_w(M0,3)); } } M0 = compute_M0(bound, N); if (DEBUGLEVEL>1) { err_printf("M0 = %Ps\n",gprec_w(M0,3)); 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 = %Ps\n",gprec_w(M,3)); 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 = 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; byteptr delta = diffptr + 1; ulong bound, p; struct check_pr S; 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>1) { err_printf("\nPHASE 2: are all primes good ?\n\n"); err_printf(" Testing primes <= %Ps\n\n", B); err_flush(); } bound = itou_or_0(B); if (!bound) pari_err(talker,"sorry, too many primes to check"); maxprime_check(bound); for (p = 2; p <= bound; ) { check_prime(p,bnf, &S); NEXT_PRIME_VIADIFF(p, delta); } 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, Delta = diagonal_shallow( bnr_get_cyc(bnr2) ); /* SNF of Cl_n */ if (!H) return Delta; H2 = ZM_mul(bnrsurjection(bnr, bnr2), H); return ZM_hnf( shallowconcat(H2, Delta) ); /* 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(talker,"missing conductor in ABC_to_bnr"); *H = C; return Buchray(A,B, gen? nf_INIT | nf_GEN: nf_INIT); } pari_err(typeer,"ABC_to_bnr"); *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); } static GEN check_subgroup(GEN bnr, GEN H, GEN *clhray, int triv_is_NULL, const char *s) { GEN h, D = NULL; if (H && gequal0(H)) H = NULL; if (H) { D = diagonal_shallow(bnr_get_cyc(bnr)); if (typ(H) != t_MAT) pari_err(typeer,"check_subgroup"); RgM_check_ZM(H, "check_subgroup"); H = ZM_hnf(H); if (!hnfdivide(H, D)) pari_err(talker,"incorrect subgroup in %s", s); h = ZM_det_triangular(H); if (equalii(h, *clhray)) H = NULL; else *clhray = h; } if (!H && !triv_is_NULL) H = D? D: diagonal_shallow(bnr_get_cyc(bnr)); return 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): lg(z[1]); lU = lg(U); if (lz != lU) { if (lz == 1) return zerocol(lg(U[1]) - 1); /* 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, "conductor"); 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, "conductor"); 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; } /* 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 famo, fac, col, cnd; byteptr d = diffptr; ulong p; checkbnr(bnr); bnf = bnr_get_bnf(bnr); nf = bnf_get_nf(bnf); cnd = gel(bnr_get_mod(bnr), 1); polrel = rnf_fix_pol(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 */ polr = nfX_to_FqX(polrel, nf, modpr); /* in Fp[X] */ if (!FpX_is_squarefree(polr, pp)) { oldf = 0; continue; } famo = FpX_factor(polr, pp); fac = gel(famo,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) pari_err(talker,"non Galois extension in rnfnormgroup"); 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 = gmulsg(f, bnrisprincipal(bnr,pr,0)); group = ZM_hnf(shallowconcat(group, col)); detgroup = ZM_det_triangular(group); k = cmpiu(detgroup,reldeg); if (k < 0) pari_err(talker,"not an Abelian extension in rnfnormgroup"); if (!k) { cgiv(detgroup); return gerepileupto(av,group); } } } } static GEN liftpol(GEN pol, GEN q) { long i, l = lg(pol); GEN y = cgetg(l, t_POL); y[1] = pol[1]; for (i = 2; i < l; i++) gel(y,i) = lift_intern(poleval(lift_intern(gel(pol,i)), q)); return y; } GEN nf_deg1_prime(GEN nf) { GEN bad = mulii(nf_get_disc(nf), nf_get_index(nf)); GEN T = nf_get_pol(nf), p, z; long degnf = degpol(T); byteptr pt = diffptr; ulong pp = init_primepointer(degnf, 0, &pt); for(;;) { pari_sp av = avma; NEXT_PRIME_VIADIFF_CHECK(pp, pt); if (umodiu(bad, pp) == 0) continue; p = utoipos(pp); z = FpX_roots(FpX_red(T, p), p); if (lg(z) > 1) break; avma = av; } z = deg1pol_shallow(gen_1, negi(gel(z,1)), varn(T)); return primedec_apply_kummer(nf, z, 1, p); } long rnfisabelian(GEN nf, GEN pol) { GEN modpr, pr, T, pp, ro, nfL, C, z, a, sig, eq; long i, j, l, v; ulong p, k, ka; if (typ(nf) == t_POL) v = varn(nf); else { nf = checknf(nf); v = nf_get_varn(nf); } eq = rnfequation2(nf,pol); C = gel(eq,1); setvarn(C, v); a = lift_intern(gel(eq,2)); setvarn(a, v); /* root of nf[1] */ z = nfroots_split(C, liftpol(pol, a)); 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(typeer,"KerChar"); if (lg(chi) != l) pari_err(talker,"incorrect character length in KerChar"); 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(typeer, s); if (lg(z) == 1) return; z = gel(z,1); /* [bid,U] */ if (typ(z) != t_VEC || lg(z) != 3) pari_err(typeer, s); 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) { P[c] = 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, j, lz, l = lg(L); GEN nf, v, z, V, D, 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 = Z_factor(absi(nf_get_disc(nf))); ID.idealrelinit = trivfact(); V = cgetg(l, t_VEC); D = 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); gel(D,i) = d = cgetg(lz,t_VEC); for (j=1; j>SHLGVINT) + 1; } INLINE long vext1(long 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 b, m, qm, 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(talker,"not a factorisation in decodemodule"); n = nf_get_degree(nf); nn = n*n; id = NULL; G = gel(fa,1); E = gel(fa,2); for (k=1; k15) pari_err(talker,"r1>15 in discrayabslistarch"); nba = r1; } else { matarchunit = NULL; for (nba=0,i=1; i<=r1; i++) if (signe(arch[i])) nba++; } /* what follows was rewritten from Ideallist */ p = utoipos(2); av = avma; lim = stack_lim(av,1); sqbou = (long)sqrt((double)bound) + 1; Z = bigcgetvec(bound); for (i=2; i<=bound; i++) bigel(Z,i) = cgetg(1,t_VEC); embunit = zlog_units(nf, U, sgnU, bidp); bigel(Z,1) = mkvec(zsimp(bidp,embunit)); if (DEBUGLEVEL>1) err_printf("Starting zidealstarunits computations\n"); maxprime_check((ulong)bound); /* 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] <= bound) { if (!flbou && 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) continue; /* 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 */ { bidp = Idealstar(nf,ideal, nf_INIT); embunit = zlog_units_noarch(nf, U, bidp); for (i=Q; i<=bound; i+=Q) { GEN pz, p2, p1 = bigel(Z,i/Q); 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,i); if (flbou) p2 = bnrclassnointernarch(p2,h,matarchunit); if (lg(pz) > 1) p2 = shallowconcat(pz,p2); bigel(Ray,i) = p2; } Q = itos_or_0( mulss(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); } NEXT_PRIME_VIADIFF(p[2], dif); } 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=_",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*)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."}, {"_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*)gach,3,"Gp","acosh(x)=inverse hyperbolic cosine of x."}, {"addell",3,(void*)addell,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)=(long)gen_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)=(long)gen_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*)gch,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*)divsum,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*)ggamd,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)=(long)gen_2-element representation of an ideal x in the number field nf."}, {"idealtwoelt2",3,(void*)idealtwoelt2,6,"GGG","idealtwoelt2(nf,x,a)=(long)gen_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,"Gp","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*)gisfundamental,4,"G","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*)gisirreducible,7,"G","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*)gissquarefree,4,"G","issqfree(x)=true(1) if x is squarefree, false(0) if not."}, {"issquare",1,(void*)gissquare,4,"G","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*)gkronecker,4,"GG","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*)gmoebius,4,"G","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*)numbdiv,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*)gomega,4,"G","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*)ordred,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*)geulerphi,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*)powell,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*)znprimroot0,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*)recip,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",1,(void*)roots0,7,"GD1,L,p","rootsold(x)=roots of the polynomial x using a modified Newton's method."}, {"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,"Gn","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*)gsh,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*)smallellinit,5,"Gp","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*)subell,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*)gth,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*)ggval,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.5.5/src/language/default.h0000644000175000017500000000240112201011602015231 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,"",""}, {"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,"",""}, {"strictmatch",0,(void*)sd_strictmatch,16,"",""}, {NULL,0,NULL,0,NULL,NULL} /* sentinel */ }; pari-2.5.5/src/language/errmsg.c0000644000175000017500000000346612147140047015132 0ustar billbill/* $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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pari.h" const char *errmessage[]= { "", /* force error into non-0 */ "", /* syntaxer */ "", /* bugparier */ "", /* alarmer */ "", /* openfiler */ "", /* talker */ "invalid flag", /* flagerr */ "", /* impl */ "sorry, not yet available on this system", /* archer */ "not a function in function call", /* notfuncer */ "precision too low", /* precer */ "incorrect type", /* typeer */ "inconsistent data", /* consister */ "", /* user */ "the PARI stack overflows !", /* errpile */ "", /* overflower */ /* ALGLIN.C */ "non invertible matrix in gauss", /* matinv1 */ "not a square matrix", /* mattype1 */ /* ARITH.C */ "not an integer argument in an arithmetic function", /* arither1 */ "not enough precomputed primes", /* primer1 */ "", /* invmoder*/ /* BASE.C */ "constant polynomial", /* constpoler */ "not a polynomial", /* notpoler */ "reducible polynomial", /* redpoler */ "zero polynomial", /* zeropoler */ /* GEN.C */ "", /* operi */ "", /* operf */ "division by zero", /* gdiver */ /* INIT.C */ "not enough memory", /* memer */ /* TRANS.C */ "negative exponent", /* negexper */ "non quadratic residue in gsqrt", /* sqrter5 */ "what's going on ?" /* noer */ }; pari-2.5.5/src/language/anal.c0000644000175000017500000006577312147140046014556 0ustar billbill/* $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. */ #include "pari.h" #include "paripriv.h" #include "anal.h" #include "parse.h" /*************************************************************************** ** ** ** Mnemonic codes parser ** ** ** ***************************************************************************/ /* TEMPLATE is assumed to be ";"-separated list of items. Each item * may have one of the following forms: id=value id==value id|value id&~value. * Each id consists of alphanum characters, dashes and underscores. * IDs are case-sensitive. * ARG consists of several IDs separated by punctuation (and optional * whitespace). Each modifies the return value in a "natural" way: an * ID from id=value should be the first in the sequence and sets RETVAL to * VALUE (and cannot be negated), ID from id|value bit-ORs RETVAL with * VALUE (and bit-ANDs RETVAL with ~VALUE if negated), ID from * id&~value behaves as if it were noid|value, ID from * id==value behaves the same as id=value, but should come alone. * For items of the form id|value and id&~value negated forms are * allowed: either when arg looks like no[-_]id, or when id looks like * this, and arg is not-negated. */ enum { A_ACTION_ASSIGN, A_ACTION_SET, A_ACTION_UNSET }; #define IS_ID(c) (isalnum((int)c) || ((c) == '_') || ((c) == '-')) long eval_mnemonic(GEN str, const char *tmplate) { pari_sp av=avma; ulong retval = 0; const char *etmplate = NULL; const char *arg; if (typ(str)==t_INT) return itos(str); if (typ(str)!=t_STR) pari_err(talker,"invalid flag"); arg=GSTR(str); etmplate = strchr(tmplate, '\n'); if (!etmplate) etmplate = tmplate + strlen(tmplate); while (1) { long numarg; const char *e, *id; const char *negated; /* action found with 'no'-ID */ int negate; /* Arg has 'no' prefix removed */ ulong l, action = 0, first = 1, singleton = 0; char *buf, *inibuf; static char b[80]; while (isspace((int)*arg)) arg++; if (!*arg) break; e = arg; while (IS_ID(*e)) e++; /* Now the ID is whatever is between arg and e. */ l = e - arg; if (l >= sizeof(b)) pari_err(talker,"id too long in a stringified flag"); if (!l) /* Garbage after whitespace? */ pari_err(talker,"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(talker,"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(talker,"Unrecognized id '%s' in a stringified flag", inibuf); if (singleton && !first) pari_err(talker,"Singleton id non-single in a stringified flag"); if (id[0] == '=') { if (negate) pari_err(talker,"Cannot negate id=value in a stringified flag"); if (!first) pari_err(talker,"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(talker, "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(talker, "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(talker,"error in parse_option_string"); } first = 0; while (isspace((int)*arg)) arg++; if (*arg && !(ispunct((int)*arg) && *arg != '-')) pari_err(talker,"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 'E': case 'L': case 'M': case 'P': case 'W': case 'f': case 'n': case 'p': case 'r': case 'x': arity++; break; 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(syntaxer, "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(syntaxer, "this code has to come first", s-1, code); default: pari_err(syntaxer, "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, char *name, 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(talker,"[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 { char *s = name; if (isalpha((int)*s)) while (is_keyword_char(*++s)) /* empty */; if (*s) pari_err(syntaxer,"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(talker,"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 */ /* */ /*******************************************************************/ static ulong number(int *n, const char **s) { ulong m = 0; for (*n = 0; *n < 9 && 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 }; 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)) { 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 = lgefint(y); if (l < (long)PREC) l = (long)PREC; if (!n) return itor(y, l); y = itor(y, l+1); if (n > 0) y = mulrr(y, rpowuu(10UL, (ulong)n, l+1)); else y = divrr(y, rpowuu(10UL, (ulong)-n, l+1)); return gerepileuptoleaf(av, rtor(y, l)); } static GEN int_read(const char **s) { int nb; GEN y = utoi(number(&nb, s)); if (nb == 9) 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 (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=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 *(*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; if (foreignAutoload) /* Try to autoload. */ return foreignAutoload(name,len); 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(talker,"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(talker,"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(talker,"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(initial_value(ep)); } pari_err(talker, "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(talker, "%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( 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(talker, "renaming a GP variable is forbidden"); if (n > (long)MAXVARN) pari_err(talker, "variable number too big"); 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) pari_err(typeer,"gpolvar"); 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(talker,"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 andpari(GEN a, GEN b/*closure*/) { GEN g; if (gequal0(a)) return gen_0; g=closure_evalgen(b); if (!g) return g; return gequal0(g)?gen_0:gen_1; } GEN orpari(GEN a, GEN b/*closure*/) { GEN g; if (!gequal0(a)) return gen_1; g=closure_evalgen(b); if (!g) return g; return gequal0(g)?gen_0:gen_1; } GEN gstore(GEN *x, GEN y) { *x=y; return *x; } GEN gmule(GEN *x, GEN y) { *x=gmul(*x,y); return *x; } GEN gdive(GEN *x, GEN y) { *x=gdiv(*x,y); return *x; } GEN gdivente(GEN *x, GEN y) { *x=gdivent(*x,y); return *x; } GEN gdivrounde(GEN *x, GEN y) { *x=gdivround(*x,y); return *x; } GEN gmode(GEN *x, GEN y) { *x=gmod(*x,y); return *x; } GEN gshiftle(GEN *x, long n) { *x=gshift(*x,n); return *x; } GEN gshiftre(GEN *x, long n) { *x=gshift(*x,-n); return *x; } GEN gadde(GEN *x, GEN y) { *x=gadd(*x,y); return *x; } GEN gadd1e(GEN *x) { *x=typ(*x)==t_INT?addis(*x,1):gaddgs(*x,1); return *x; } GEN gsube(GEN *x, GEN y) { *x=gsub(*x,y); return *x; } GEN gsub1e(GEN *x) { *x=typ(*x)==t_INT?subis(*x,1):gsubgs(*x,1); return *x; } GEN gshift_right(GEN x, long n) { return gshift(x,-n); } /********************************************************************/ /** **/ /** PRINT USER FUNCTION AND MEMBER FUNCTION **/ /** **/ /********************************************************************/ static int cmp_epname(void *E, GEN e, GEN f) { (void)E; return strcmp(((entree*)e)->name, ((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); const char *f; entree *ep; int i; for (i = 0; i < functions_tblsz; i++) for (ep = functions_hash[i]; ep; ep = ep->next) { int is_member; if (EpVALENCE(ep) != EpVAR || typ(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]; f = ep->name; pari_printf("%s =\n %Ps\n\n", f, ep->value); } } avma = av; } pari-2.5.5/src/language/init.c0000644000175000017500000014360312162150422014567 0ustar billbill/* $Id$ 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 #include "pari.h" #include "paripriv.h" #include "anal.h" #ifdef _WIN32 # include "../systems/mingw/mingw.h" # ifndef WINCE # include # endif #endif 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; 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 ulong readonly_ghalf[] = { evaltyp(t_FRAC) | _evallg(3), /* ghalf */ (ulong)(readonly_constants+4), (ulong)(readonly_constants+7) }; 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; 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 *foreignHandler; /* Handler for foreign commands. */ char foreignExprSwitch = 3; /* Just some unprobable char. */ GEN (*foreignExprHandler)(char*); /* Handler for foreign expressions.*/ entree* (*foreignAutoload)(const char*, long len); /* Autoloader */ void (*foreignFuncFree)(entree *); /* How to free external entree. */ 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_err_recover)(long); typedef struct { jmp_buf *penv; long flag; } cell; static THREAD pari_stack s_ERR_CATCH; static THREAD cell *ERR_CATCH; THREAD void *global_err_data; 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; } 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; 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 *stack_base) { (void) stack_base; if (!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 *stack_base) { struct rlimit rip; ulong size; if (!stack_base) { PARI_stack_limit = NULL; return; } if (getrlimit(RLIMIT_STACK, &rip)) return; size = rip.rlim_cur; if (size == (ulong)RLIM_INFINITY || size > (ulong)stack_base) PARI_stack_limit = (void*)(((ulong)stack_base) / 16); else PARI_stack_limit = (void*)((ulong)stack_base - (size/16)*15); } # endif /* !__EMX__ */ #else void pari_stackcheck_init(void *stack_base) { (void) 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; VOLATILE THREAD 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(talker, "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) PARI_SIGINT_pending=SIGBREAK; else pari_handle_SIGINT(); return; #endif #ifdef SIGINT case SIGINT: if (PARI_SIGINT_block) PARI_SIGINT_pending=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(talker, "Broken Pipe, resetting file stack..."); } /*Do not attempt to write to stdout in case it triggered the SIGPIPE*/ return; /* not reached */ } #endif default: msg="signal handling"; break; } pari_err(bugparier,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; } 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 (;; s>>=1) { char buf[128]; if (s < MIN_STACK) pari_err(memer); /* no way out. Die */ s = fix_size(s); bot = (pari_sp)malloc(s); /* NOT pari_malloc, memer would be deadly */ if (bot) break; /* must use sprintf: pari stack is currently dead */ sprintf(buf, "not enough memory, new stack %lu", (ulong)s); pari_warn(warner, buf, s); } BLOCK_SIGINT_END; } avma = top = bot+s; memused = 0; } 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.); global_err_data = NULL; 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) { #ifdef _WIN32 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 **)*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) { stack_init(&s_MODULES, sizeof(*MODULES),(void**)&MODULES); stack_pushp(&s_MODULES,functions_basic); stack_init(&s_OLDMODULES, sizeof(*OLDMODULES),(void**)&OLDMODULES); 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); 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); stack_pushp(&s_OLDMODULES, ep); } static void pari_init_errcatch(void) { stack_init(&s_ERR_CATCH, sizeof(cell), (void**)&ERR_CATCH); global_err_data = NULL; } /*********************************************************************/ /* PARI THREAD */ /*********************************************************************/ static void pari_stack_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_stack_free(struct pari_mainstack *st) { free((void*)st->bot); st->avma = st->top = st->bot = 0; } static void pari_stack_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_stack_alloc(&t->st,s); t->data = arg; } void pari_thread_free(struct pari_thread *t) { pari_stack_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_stack_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_sigint = dflt_sigint_fun; if ((init_opts&INIT_JMPm)) cb_pari_err_recover = dflt_err_recover; pari_stackcheck_init(&u); 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); diffptr = initprimes(maxprime); init_universal_constants(); if (pari_kernel_init()) pari_err(talker,"Cannot initialize kernel"); 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(); try_to_recover = 1; } 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); 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(); free((void*)functions_hash); free((void*)defaults_hash); free((void*)bot); free((void*)diffptr); free(current_logfile); free(current_psfile); stack_delete(&s_MODULES); stack_delete(&s_OLDMODULES); if (pari_datadir) free(pari_datadir); if (init_opts&INIT_DFTm) { /* delete GP_DATA */ if (GP_DATA->hist->res) free((void*)GP_DATA->hist->res); 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->listloc = next_block; rec->err_catch = s_ERR_CATCH.n; 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); s_ERR_CATCH.n = rec->err_catch; global_err_data = rec->err_data; 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; } long err_catch(long errnum, jmp_buf *penv) { long n; /* for fear of infinite recursion */ if (errnum == memer) pari_err(talker, "can't trap memory errors"); if (errnum == CATCH_ALL) errnum = noer; else if (errnum > noer) pari_err(talker, "no such error number: %ld", errnum); n = stack_new(&s_ERR_CATCH); ERR_CATCH[n].flag = errnum; ERR_CATCH[n].penv = penv; return n; } /* delete traps younger than n (included) */ void err_leave(long n) { if (n >= 0) s_ERR_CATCH.n = n; } /* Get last (most recent) handler for error n (or generic noer) killing all * more recent non-applicable handlers (now obsolete) */ static cell * err_seek(long n) { if (n == bugparier) return NULL; for( ; s_ERR_CATCH.n; s_ERR_CATCH.n--) { cell *t = &ERR_CATCH[ s_ERR_CATCH.n-1 ]; if (t->flag == n || t->flag == noer) return t; } return NULL; } void err_recover(long numerr) { evalstate_reset(); initout(0); killallfiles(); s_ERR_CATCH.n = 0; dbg_release(); global_err_data = NULL; 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) { 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); switch (numerr) { case user: out_puts(pariErr, "user warning: "); out_print0(pariErr, 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) { err_init(); closure_err(); err_init_msg(talker); out_puts(pariErr, "user interrupt after "); out_puts(pariErr, time_s); out_term_color(pariErr, c_NONE); pariErr->flush(); if (cb_pari_handle_exception && cb_pari_handle_exception(-1)) return; err_recover(talker); } void pari_err(int numerr, ...) { va_list ap; va_start(ap,numerr); global_err_data = NULL; if (s_ERR_CATCH.n) { cell *trapped; if ( (trapped = err_seek(numerr)) ) { switch(numerr) { case invmoder: global_err_data = (void*)va_arg(ap, GEN); break; case alarmer: global_err_data = (char*)va_arg(ap, char*); break; } longjmp(*(trapped->penv), numerr); } } err_init(); if (numerr == syntaxer) { const char *msg = va_arg(ap, char*); const char *s = va_arg(ap,char *); print_errcontext(pariErr, msg,s,va_arg(ap,char *)); } else { closure_err(); err_init_msg(numerr); out_puts(pariErr, errmessage[numerr]); switch (numerr) { case talker: { const char *ch1 = va_arg(ap, char*); out_vprintf(pariErr, ch1,ap); out_putc(pariErr, '.'); break; } case alarmer: { const char *ch1 = va_arg(ap, char*); out_puts(pariErr, "alarm interrupt after "); out_vprintf(pariErr, ch1,ap); out_putc(pariErr, '.'); break; } case user: out_puts(pariErr, "user error: "); out_print0(pariErr, va_arg(ap, GEN), f_RAW); break; case invmoder: out_printf(pariErr, "impossible inverse modulo: %Ps." , va_arg(ap, GEN)); break; case openfiler: { const char *type = va_arg(ap, char*); out_printf(pariErr, "error opening %s file: `%s'." , type, va_arg(ap,char*)); break; } case overflower: out_printf(pariErr, "overflow in %s.", va_arg(ap, char*)); break; case notfuncer: { GEN fun = va_arg(ap, GEN); if (gcmpX(fun)) { entree *ep = varentries[varn(fun)]; const char *s = ep->name; if (cb_pari_whatnow) cb_pari_whatnow(pariErr, s,1); } break; } case impl: out_printf(pariErr, "sorry, %s is not yet implemented." , va_arg(ap, char*)); break; case typeer: case mattype1: case negexper: case constpoler: case notpoler: case redpoler: case zeropoler: case consister: case flagerr: case precer: out_printf(pariErr, " in %s.",va_arg(ap, char*)); break; case bugparier: out_printf(pariErr, "bug in %s, please report" , va_arg(ap, char*)); break; case operi: case operf: { const char *f, *op = va_arg(ap, const char*); GEN x = va_arg(ap, GEN); GEN y = va_arg(ap, GEN); out_puts(pariErr, numerr == operi? "impossible": "forbidden"); switch(*op) { case '+': f = "addition"; break; case '-': out_printf(pariErr, " negation - %s.",type_name(typ(x))); f = NULL; break; case '*': f = "multiplication"; break; case '/': case '%': case '\\': f = "division"; break; case 'g': op = ","; f = "gcd"; break; default: op = "-->"; f = "assignment"; break; } if (f) out_printf(pariErr, " %s %s %s %s." , f,type_name(typ(x)),op,type_name(typ(y))); break; } case primer1: { ulong c = va_arg(ap, ulong); if (c) out_printf(pariErr, ", need primelimit ~ %lu.", c); break; } } } out_term_color(pariErr, c_NONE); va_end(ap); if (numerr==errpile) { size_t d = top - bot; char buf[256]; /* don't use pari_printf: it needs the PARI stack for %.3f conversion */ sprintf(buf, "\n current stack size: %lu (%.3f Mbytes)\n", (ulong)d, (double)d/1048576.); pariErr->puts(buf); pariErr->puts(" [hint] you can increase GP stack with allocatemem()\n"); } pariErr->flush(); if (cb_pari_handle_exception && cb_pari_handle_exception(numerr)) return; err_recover(numerr); } /* 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 if (!strcmp(e,"alarmer")) numerr = alarmer; else if (!strcmp(e,"archer")) numerr = archer; else if (!strcmp(e,"errpile")) numerr = errpile; else if (!strcmp(e,"gdiver")) numerr = gdiver; else if (!strcmp(e,"impl")) numerr = impl; else if (!strcmp(e,"invmoder")) numerr = invmoder; else if (!strcmp(e,"overflower")) numerr = overflower; else if (!strcmp(e,"syntaxer")) numerr = syntaxer; else if (!strcmp(e,"talker")) numerr = talker; else if (!strcmp(e,"typeer")) numerr = typeer; else if (!strcmp(e,"user")) numerr = user; else pari_err(impl,"this trap keyword"); /* TODO: complete the list */ 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 }; 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 = gsizeword(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= av0) { /* update address if in stack */ if (*x < tetpil) *x += dec; else pari_err(bugparier, "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\n", bot, top); for (z = (GEN)top; z >= (GEN)avma; z--) err_printf("%p:\t0x%lx\t%lu\n",z,*z,*z); } long getstack(void) { return top-avma; } /*******************************************************************/ /* */ /* timer_delay */ /* */ /*******************************************************************/ #if 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 = 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 long timer_delay(pari_timer *T) { long s = T->s, us = T->us; timer_start(T); return 1000 * (T->s - s) + (T->us - us) / 1000; } long timer_get(pari_timer *T) { pari_timer t; timer_start(&t); return 1000 * (t.s - T->s) + (t.us - T->us) / 1000; } 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; 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); } /*******************************************************************/ /* */ /* 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) { GEN v = cgetg(5, t_VEC); gel(v,1) = utoi(major); gel(v,2) = utoi(minor); gel(v,3) = utoi(patch); gel(v,4) = strtoGENstr(paricfg_vcsversion); 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 * G GEN * L long * V lexical variable * C lexical context * n variable number * & *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) * 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 prepened 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. * * Origin: * x Installed foreign function. Put the ep of the function as the * first argument, fill the rest with PARI arguments, * then call installedHandler with these arguments. * Should be the first char in the code. * **************************************************************************** */ #include "init.h" #include "default.h" pari-2.5.5/src/language/anal.h0000644000175000017500000000501312147140046014540 0ustar billbill/* $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. */ /*************************************************************************/ /* */ /* 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 /* 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]) /* 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); extern void *foreignHandler; extern GEN (*foreignExprHandler)(char*); extern char foreignExprSwitch; extern entree * (*foreignAutoload)(const char*, long len); extern void (*foreignFuncFree)(entree *); #ifdef STACK_CHECK extern THREAD void *PARI_stack_limit; #endif extern entree **varentries; struct node_loc { const char *start,*end; }; union token_value { int val; GEN gen; }; 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); const char * closure_func_err(void); GEN gp_closure(long n); long eval_mnemonic(GEN str, const char *tmplate); ENDEXTERN pari-2.5.5/src/language/parse.c0000644000175000017500000023630412147140106014740 0ustar billbill /* A Bison parser, made by GNU Bison 2.4.1. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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.4.1" /* 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 189 of yacc.c */ #line 1 "../src/language/parse.y" /* $Id$ 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" /* Line 189 of yacc.c */ #line 108 "../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, KPE = 260, KSE = 261, KME = 262, KDE = 263, KDRE = 264, KEUCE = 265, KMODE = 266, KAND = 267, KOR = 268, KID = 269, KEQ = 270, KNE = 271, KGE = 272, KLE = 273, KSRE = 274, KSLE = 275, KSR = 276, KSL = 277, KDR = 278, KPP = 279, KSS = 280, KINTEGER = 281, KREAL = 282, KENTRY = 283, KSTRING = 284, DEFFUNC = 285, SEQ = 286, LVAL = 287, INT = 288, SIGN = 289, MAT = 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 264 of yacc.c */ #line 197 "../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 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 _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # 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 _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (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) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of 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 /* YYFINAL -- State number of the termination state. */ #define YYFINAL 44 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 589 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 61 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 17 /* YYNRULES -- Number of rules. */ #define YYNRULES 96 /* YYNRULES -- Number of states. */ #define YYNSTATES 166 /* 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, 37, 53, 56, 60, 46, 41, 35, 42, 54, 45, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 57, 34, 40, 36, 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, 58, 48, 2, 59, 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, 38, 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, 47, 55 }; #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, 24, 28, 33, 38, 40, 43, 45, 48, 51, 53, 55, 57, 61, 63, 66, 68, 73, 75, 77, 79, 81, 85, 88, 91, 95, 99, 103, 107, 111, 115, 119, 123, 127, 130, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 216, 219, 223, 226, 229, 232, 235, 237, 241, 245, 247, 250, 254, 256, 260, 264, 268, 271, 275, 279, 283, 287, 289, 292, 293, 298, 300, 304, 309, 313, 320, 326, 330 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 62, 0, -1, 63, -1, 63, 1, -1, -1, 67, -1, 63, 34, -1, 63, 34, 67, -1, 52, 67, 35, 67, 58, -1, 52, 67, 58, -1, 52, 67, 35, 58, -1, 52, 35, 67, 58, -1, 59, -1, 65, 59, -1, 43, -1, 43, 26, -1, 43, 65, -1, 26, -1, 27, -1, 54, -1, 26, 54, 28, -1, 29, -1, 53, 28, -1, 66, -1, 67, 56, 74, 60, -1, 75, -1, 68, -1, 71, -1, 77, -1, 68, 36, 67, -1, 68, 24, -1, 68, 25, -1, 68, 7, 67, -1, 68, 8, 67, -1, 68, 9, 67, -1, 68, 10, 67, -1, 68, 11, 67, -1, 68, 20, 67, -1, 68, 19, 67, -1, 68, 5, 67, -1, 68, 6, 67, -1, 50, 67, -1, 49, 67, -1, 67, 13, 67, -1, 67, 38, 67, -1, 67, 12, 67, -1, 67, 37, 67, -1, 67, 14, 67, -1, 67, 15, 67, -1, 67, 16, 67, -1, 67, 17, 67, -1, 67, 39, 67, -1, 67, 18, 67, -1, 67, 40, 67, -1, 67, 42, 67, -1, 67, 41, 67, -1, 67, 22, 67, -1, 67, 21, 67, -1, 67, 43, 67, -1, 67, 23, 67, -1, 67, 44, 67, -1, 67, 45, 67, -1, 67, 46, 67, -1, 41, 67, -1, 42, 67, -1, 67, 48, 67, -1, 67, 51, -1, 67, 53, -1, 67, 50, -1, 67, 64, -1, 76, -1, 67, 57, 28, -1, 56, 67, 60, -1, 28, -1, 68, 64, -1, 68, 57, 28, -1, 67, -1, 69, 35, 67, -1, 69, 34, 69, -1, 70, 34, 69, -1, 52, 58, -1, 52, 34, 58, -1, 52, 69, 58, -1, 52, 70, 58, -1, 52, 1, 58, -1, 63, -1, 37, 68, -1, -1, 72, 1, 73, 67, -1, 72, -1, 74, 35, 72, -1, 28, 56, 74, 60, -1, 67, 54, 28, -1, 28, 56, 74, 60, 36, 63, -1, 67, 54, 28, 36, 63, -1, 68, 4, 63, -1, 56, 74, 3, 63, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { 0, 84, 84, 85, 88, 89, 90, 91, 94, 95, 96, 97, 100, 101, 104, 105, 106, 109, 110, 111, 112, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 168, 169, 170, 173, 174, 177, 178, 181, 182, 183, 184, 185, 188, 189, 190, 190, 194, 195, 198, 201, 204, 206, 208, 209 }; #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", "'^'", "'#'", "'!'", "'~'", "'['", "'\\''", "'.'", "MAT", "'('", "':'", "']'", "'`'", "')'", "$accept", "sequnused", "seq", "matrix_index", "backticks", "history", "expr", "lvalue", "matrixelts", "matrixlines", "matrix", "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, 59, 44, 61, 38, 124, 62, 60, 43, 45, 37, 92, 47, 42, 289, 94, 35, 33, 126, 91, 39, 46, 290, 40, 58, 93, 96, 41 }; # 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, 66, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 68, 68, 68, 69, 69, 70, 70, 71, 71, 71, 71, 71, 72, 72, 73, 72, 74, 74, 75, 76, 77, 77, 77, 77 }; /* 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, 5, 3, 4, 4, 1, 2, 1, 2, 2, 1, 1, 1, 3, 1, 2, 1, 4, 1, 1, 1, 1, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 2, 2, 2, 2, 1, 3, 3, 1, 2, 3, 1, 3, 3, 3, 2, 3, 3, 3, 3, 1, 2, 0, 4, 1, 3, 4, 3, 6, 5, 3, 4 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 4, 17, 18, 73, 21, 0, 0, 14, 0, 0, 0, 0, 19, 4, 0, 0, 23, 5, 26, 27, 25, 70, 28, 0, 4, 63, 64, 15, 12, 16, 42, 41, 0, 0, 80, 76, 0, 0, 22, 0, 85, 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, 0, 68, 66, 0, 67, 0, 4, 0, 69, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 0, 0, 74, 20, 0, 13, 84, 81, 0, 0, 82, 0, 83, 73, 86, 72, 87, 4, 4, 7, 45, 43, 47, 48, 49, 50, 52, 57, 56, 59, 46, 44, 51, 53, 55, 54, 58, 60, 61, 62, 65, 0, 0, 92, 0, 71, 95, 39, 40, 32, 33, 34, 35, 36, 38, 37, 29, 75, 91, 78, 77, 79, 0, 96, 0, 0, 0, 9, 4, 24, 4, 88, 11, 10, 0, 94, 93, 8 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 14, 40, 75, 29, 16, 17, 18, 36, 37, 19, 42, 150, 43, 20, 21, 22 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -55 static const yytype_int16 yypact[] = { 533, -49, -55, -28, -55, 533, 533, -25, 533, 533, 90, 15, -55, 484, 44, 12, -55, 338, 102, -55, -55, -55, -55, 45, 484, 124, 124, -55, -55, 16, -32, -24, 19, 30, -55, 338, -19, -17, -55, 46, 56, 148, 34, 5, -55, -55, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, -55, -55, 515, -55, 64, 484, 65, -55, 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, -55, -55, 533, 68, -55, -55, -33, -55, -55, -55, 533, 533, -55, 533, -55, -55, -26, -55, -55, 533, 484, 338, 382, 382, 419, 419, 419, 419, 419, 124, 124, 124, 382, 382, 419, 419, 434, 434, 124, 124, 124, 124, 124, 533, 197, 63, -31, -55, 56, 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, -55, 66, 69, 338, 69, 533, 56, 35, 244, 466, -55, 533, -55, 533, 338, -55, -55, 291, 56, 56, -55 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -55, -55, 0, -15, -55, -55, 1, 62, -54, -55, -55, -3, -55, -1, -55, -55, -55 }; /* 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 zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -91 static const yytype_int16 yytable[] = { 15, 27, 106, 90, 106, 23, 25, 26, 105, 30, 31, 35, -2, 45, 41, 96, 97, 99, 68, 69, 70, 71, 72, 92, 73, 74, 70, 146, 24, 157, 72, 89, 73, 74, 28, 104, 104, -89, -90, 98, 106, 100, 147, 38, 44, 149, 46, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, -89, -90, 130, 132, 91, 101, 93, 134, 94, 135, 136, 137, 138, 139, 140, 141, 142, 143, 90, 95, 144, 46, 32, 131, 133, -89, -90, 145, 35, 148, 156, 35, 102, 158, 152, 97, 151, 76, 77, 78, 79, 80, 81, 82, 83, 0, 0, 1, 2, 3, 4, 0, 84, 85, 0, 33, 0, 86, 87, 0, 0, 153, 5, 6, 7, 0, 0, 0, 0, 88, 8, 9, 0, 10, 11, 12, 0, 13, 0, 34, 0, 0, 159, 0, 0, 70, 162, 163, 0, 164, 89, 47, 48, 49, 50, 51, 52, 53, 0, 0, 54, 55, 56, 67, 0, 68, 69, 70, 71, 72, 0, 73, 74, 0, 0, 0, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 67, 0, 68, 69, 70, 71, 72, 0, 73, 74, 0, 0, 103, 47, 48, 49, 50, 51, 52, 53, 0, 0, 54, 55, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 0, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 67, 0, 68, 69, 70, 71, 72, 0, 73, 74, 155, 47, 48, 49, 50, 51, 52, 53, 0, 0, 54, 55, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 67, 0, 68, 69, 70, 71, 72, 0, 73, 74, 160, 47, 48, 49, 50, 51, 52, 53, 0, 0, 54, 55, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 67, 0, 68, 69, 70, 71, 72, 0, 73, 74, 165, 47, 48, 49, 50, 51, 52, 53, 0, 0, 54, 55, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 0, 67, 0, 68, 69, 70, 71, 72, 0, 73, 74, 49, 50, 51, 52, 53, 0, 0, 54, 55, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 60, 61, 62, 63, 64, 65, 66, 0, 67, 0, 68, 69, 70, 71, 72, 0, 73, 74, 54, 55, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 55, 56, 0, 0, 61, 62, 63, 64, 65, 66, 0, 67, 0, 68, 69, 70, 71, 72, 0, 73, 74, 63, 64, 65, 66, 0, 67, 0, 68, 69, 70, 71, 72, 0, 73, 74, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 1, 2, 3, 4, 0, 8, 9, 0, 10, 11, 12, 39, 13, 0, 161, 5, 6, 7, 0, 0, 0, 0, 0, 8, 9, 0, 10, 11, 12, 0, 13, 1, 2, 3, 4, 0, 0, 0, 0, 0, 129, 0, 0, 0, 0, 0, 5, 6, 7, 1, 2, 3, 4, 0, 8, 9, 0, 10, 11, 12, 0, 13, 0, 0, 5, 6, 7, 0, 0, 0, 0, 0, 8, 9, 0, 10, 11, 12, 0, 13 }; static const yytype_int16 yycheck[] = { 0, 26, 35, 18, 35, 54, 5, 6, 3, 8, 9, 10, 0, 1, 13, 34, 35, 34, 50, 51, 52, 53, 54, 24, 56, 57, 52, 60, 56, 60, 54, 57, 56, 57, 59, 1, 1, 3, 3, 58, 35, 58, 96, 28, 0, 99, 34, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 35, 35, 70, 73, 28, 28, 59, 76, 58, 77, 78, 79, 80, 81, 82, 83, 84, 85, 102, 58, 88, 34, 1, 28, 28, 60, 60, 28, 96, 97, 36, 99, 39, 36, 106, 35, 105, 4, 5, 6, 7, 8, 9, 10, 11, -1, -1, 26, 27, 28, 29, -1, 19, 20, -1, 34, -1, 24, 25, -1, -1, 129, 41, 42, 43, -1, -1, -1, -1, 36, 49, 50, -1, 52, 53, 54, -1, 56, -1, 58, -1, -1, 150, -1, -1, 52, 154, 156, -1, 158, 57, 12, 13, 14, 15, 16, 17, 18, -1, -1, 21, 22, 23, 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, -1, -1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, -1, 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, -1, -1, 60, 12, 13, 14, 15, 16, 17, 18, -1, -1, 21, 22, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, -1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, -1, 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, 58, 12, 13, 14, 15, 16, 17, 18, -1, -1, 21, 22, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, -1, 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, 58, 12, 13, 14, 15, 16, 17, 18, -1, -1, 21, 22, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, -1, 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, 58, 12, 13, 14, 15, 16, 17, 18, -1, -1, 21, 22, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, -1, 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, 14, 15, 16, 17, 18, -1, -1, 21, 22, 23, -1, -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, -1, 56, 57, 21, 22, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, 22, 23, -1, -1, 41, 42, 43, 44, 45, 46, -1, 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, 43, 44, 45, 46, -1, 48, -1, 50, 51, 52, 53, 54, -1, 56, 57, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, 42, 43, 26, 27, 28, 29, -1, 49, 50, -1, 52, 53, 54, 37, 56, -1, 58, 41, 42, 43, -1, -1, -1, -1, -1, 49, 50, -1, 52, 53, 54, -1, 56, 26, 27, 28, 29, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, 41, 42, 43, 26, 27, 28, 29, -1, 49, 50, -1, 52, 53, 54, -1, 56, -1, -1, 41, 42, 43, -1, -1, -1, -1, -1, 49, 50, -1, 52, 53, 54, -1, 56 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 26, 27, 28, 29, 41, 42, 43, 49, 50, 52, 53, 54, 56, 62, 63, 66, 67, 68, 71, 75, 76, 77, 54, 56, 67, 67, 26, 59, 65, 67, 67, 1, 34, 58, 67, 69, 70, 28, 37, 63, 67, 72, 74, 0, 1, 34, 12, 13, 14, 15, 16, 17, 18, 21, 22, 23, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 48, 50, 51, 52, 53, 54, 56, 57, 64, 4, 5, 6, 7, 8, 9, 10, 11, 19, 20, 24, 25, 36, 57, 64, 28, 74, 59, 58, 58, 34, 35, 58, 34, 58, 28, 68, 60, 1, 3, 35, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 35, 67, 28, 74, 28, 63, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 28, 60, 69, 67, 69, 73, 63, 72, 67, 35, 58, 36, 60, 36, 67, 58, 58, 67, 63, 63, 58 }; #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. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ 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 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 YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*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 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1349 "../src/language/parse.c" break; case 64: /* "matrix_index" */ /* Line 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1358 "../src/language/parse.c" break; case 65: /* "backticks" */ /* Line 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1367 "../src/language/parse.c" break; case 66: /* "history" */ /* Line 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1376 "../src/language/parse.c" break; case 67: /* "expr" */ /* Line 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1385 "../src/language/parse.c" break; case 68: /* "lvalue" */ /* Line 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1394 "../src/language/parse.c" break; case 69: /* "matrixelts" */ /* Line 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1403 "../src/language/parse.c" break; case 70: /* "matrixlines" */ /* Line 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1412 "../src/language/parse.c" break; case 71: /* "matrix" */ /* Line 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1421 "../src/language/parse.c" break; case 72: /* "arg" */ /* Line 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1430 "../src/language/parse.c" break; case 74: /* "listarg" */ /* Line 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1439 "../src/language/parse.c" break; case 75: /* "funcid" */ /* Line 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1448 "../src/language/parse.c" break; case 76: /* "memberid" */ /* Line 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1457 "../src/language/parse.c" break; case 77: /* "definition" */ /* Line 1000 of yacc.c */ #line 81 "../src/language/parse.y" { pari_discarded++; }; /* Line 1000 of yacc.c */ #line 1466 "../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 or yypush_parse. | `-------------------------*/ #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[2]; 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 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 1242 of yacc.c */ #line 31 "../src/language/parse.y" { yylloc.start=yylloc.end=*lex; } /* Line 1242 of yacc.c */ #line 1619 "../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 (yyn == YYPACT_NINF) 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 (yyn == 0 || yyn == YYTABLE_NINF) 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 1455 of yacc.c */ #line 84 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);;} break; case 3: /* Line 1455 of yacc.c */ #line 85 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (2)].val); pari_unused_chars=(yylsp[(1) - (2)]).end;YYABORT;;} break; case 4: /* Line 1455 of yacc.c */ #line 88 "../src/language/parse.y" {(yyval.val)=newnode(Fnoarg,-1,-1,&(yyloc));;} break; case 5: /* Line 1455 of yacc.c */ #line 89 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);;} break; case 6: /* Line 1455 of yacc.c */ #line 90 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (2)].val); (yyloc)=(yylsp[(1) - (2)]);;} break; case 7: /* Line 1455 of yacc.c */ #line 91 "../src/language/parse.y" {(yyval.val)=newnode(Fseq,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 8: /* Line 1455 of yacc.c */ #line 94 "../src/language/parse.y" {(yyval.val)=newnode(Fmatrix,(yyvsp[(2) - (5)].val),(yyvsp[(4) - (5)].val),&(yyloc));;} break; case 9: /* Line 1455 of yacc.c */ #line 95 "../src/language/parse.y" {(yyval.val)=newnode(Fmatrix,(yyvsp[(2) - (3)].val),-1,&(yyloc));;} break; case 10: /* Line 1455 of yacc.c */ #line 96 "../src/language/parse.y" {(yyval.val)=newnode(FmatrixL,(yyvsp[(2) - (4)].val),-1,&(yyloc));;} break; case 11: /* Line 1455 of yacc.c */ #line 97 "../src/language/parse.y" {(yyval.val)=newnode(FmatrixR,(yyvsp[(3) - (4)].val),-1,&(yyloc));;} break; case 12: /* Line 1455 of yacc.c */ #line 100 "../src/language/parse.y" {(yyval.val)=1;;} break; case 13: /* Line 1455 of yacc.c */ #line 101 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (2)].val)+1;;} break; case 14: /* Line 1455 of yacc.c */ #line 104 "../src/language/parse.y" {(yyval.val)=newopcall(OPhist,-1,-1,&(yyloc));;} break; case 15: /* Line 1455 of yacc.c */ #line 105 "../src/language/parse.y" {(yyval.val)=newopcall(OPhist,newintnode(&(yylsp[(2) - (2)])),-1,&(yyloc));;} break; case 16: /* Line 1455 of yacc.c */ #line 106 "../src/language/parse.y" {(yyval.val)=newopcall(OPhist,newnode(Fsmall,-(yyvsp[(2) - (2)].val),-1,&(yyloc)),-1,&(yyloc));;} break; case 17: /* Line 1455 of yacc.c */ #line 109 "../src/language/parse.y" {(yyval.val)=newintnode(&(yylsp[(1) - (1)]));;} break; case 18: /* Line 1455 of yacc.c */ #line 110 "../src/language/parse.y" {(yyval.val)=newconst(CSTreal,&(yyloc));;} break; case 19: /* Line 1455 of yacc.c */ #line 111 "../src/language/parse.y" {(yyval.val)=newconst(CSTreal,&(yyloc));;} break; case 20: /* Line 1455 of yacc.c */ #line 112 "../src/language/parse.y" {(yyval.val)=newnode(Ffunction,newconst(CSTmember,&(yylsp[(3) - (3)])), newintnode(&(yylsp[(1) - (3)])),&(yyloc));;} break; case 21: /* Line 1455 of yacc.c */ #line 114 "../src/language/parse.y" {(yyval.val)=newconst(CSTstr,&(yyloc));;} break; case 22: /* Line 1455 of yacc.c */ #line 115 "../src/language/parse.y" {(yyval.val)=newconst(CSTquote,&(yyloc));;} break; case 23: /* Line 1455 of yacc.c */ #line 116 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);;} break; case 24: /* Line 1455 of yacc.c */ #line 117 "../src/language/parse.y" {(yyval.val)=newnode(Fcall,(yyvsp[(1) - (4)].val),(yyvsp[(3) - (4)].val),&(yyloc));;} break; case 25: /* Line 1455 of yacc.c */ #line 118 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);;} break; case 26: /* Line 1455 of yacc.c */ #line 119 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);;} break; case 27: /* Line 1455 of yacc.c */ #line 120 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);;} break; case 28: /* Line 1455 of yacc.c */ #line 121 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);;} break; case 29: /* Line 1455 of yacc.c */ #line 122 "../src/language/parse.y" {(yyval.val)=newnode(Faffect,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 30: /* Line 1455 of yacc.c */ #line 123 "../src/language/parse.y" {(yyval.val)=newopcall(OPpp,(yyvsp[(1) - (2)].val),-1,&(yyloc));;} break; case 31: /* Line 1455 of yacc.c */ #line 124 "../src/language/parse.y" {(yyval.val)=newopcall(OPss,(yyvsp[(1) - (2)].val),-1,&(yyloc));;} break; case 32: /* Line 1455 of yacc.c */ #line 125 "../src/language/parse.y" {(yyval.val)=newopcall(OPme,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 33: /* Line 1455 of yacc.c */ #line 126 "../src/language/parse.y" {(yyval.val)=newopcall(OPde,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 34: /* Line 1455 of yacc.c */ #line 127 "../src/language/parse.y" {(yyval.val)=newopcall(OPdre,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 35: /* Line 1455 of yacc.c */ #line 128 "../src/language/parse.y" {(yyval.val)=newopcall(OPeuce,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 36: /* Line 1455 of yacc.c */ #line 129 "../src/language/parse.y" {(yyval.val)=newopcall(OPmode,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 37: /* Line 1455 of yacc.c */ #line 130 "../src/language/parse.y" {(yyval.val)=newopcall(OPsle,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 38: /* Line 1455 of yacc.c */ #line 131 "../src/language/parse.y" {(yyval.val)=newopcall(OPsre,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 39: /* Line 1455 of yacc.c */ #line 132 "../src/language/parse.y" {(yyval.val)=newopcall(OPpe,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 40: /* Line 1455 of yacc.c */ #line 133 "../src/language/parse.y" {(yyval.val)=newopcall(OPse,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 41: /* Line 1455 of yacc.c */ #line 134 "../src/language/parse.y" {(yyval.val)=newopcall(OPnb,(yyvsp[(2) - (2)].val),-1,&(yyloc));;} break; case 42: /* Line 1455 of yacc.c */ #line 135 "../src/language/parse.y" {(yyval.val)=newopcall(OPlength,(yyvsp[(2) - (2)].val),-1,&(yyloc));;} break; case 43: /* Line 1455 of yacc.c */ #line 136 "../src/language/parse.y" {(yyval.val)=newopcall(OPor,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 44: /* Line 1455 of yacc.c */ #line 137 "../src/language/parse.y" {(yyval.val)=newopcall(OPor,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 45: /* Line 1455 of yacc.c */ #line 138 "../src/language/parse.y" {(yyval.val)=newopcall(OPand,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 46: /* Line 1455 of yacc.c */ #line 139 "../src/language/parse.y" {(yyval.val)=newopcall(OPand,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 47: /* Line 1455 of yacc.c */ #line 140 "../src/language/parse.y" {(yyval.val)=newopcall(OPid,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 48: /* Line 1455 of yacc.c */ #line 141 "../src/language/parse.y" {(yyval.val)=newopcall(OPeq,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 49: /* Line 1455 of yacc.c */ #line 142 "../src/language/parse.y" {(yyval.val)=newopcall(OPne,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 50: /* Line 1455 of yacc.c */ #line 143 "../src/language/parse.y" {(yyval.val)=newopcall(OPge,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 51: /* Line 1455 of yacc.c */ #line 144 "../src/language/parse.y" {(yyval.val)=newopcall(OPg,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 52: /* Line 1455 of yacc.c */ #line 145 "../src/language/parse.y" {(yyval.val)=newopcall(OPle,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 53: /* Line 1455 of yacc.c */ #line 146 "../src/language/parse.y" {(yyval.val)=newopcall(OPl,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 54: /* Line 1455 of yacc.c */ #line 147 "../src/language/parse.y" {(yyval.val)=newopcall(OPs,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 55: /* Line 1455 of yacc.c */ #line 148 "../src/language/parse.y" {(yyval.val)=newopcall(OPp,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 56: /* Line 1455 of yacc.c */ #line 149 "../src/language/parse.y" {(yyval.val)=newopcall(OPsl,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 57: /* Line 1455 of yacc.c */ #line 150 "../src/language/parse.y" {(yyval.val)=newopcall(OPsr,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 58: /* Line 1455 of yacc.c */ #line 151 "../src/language/parse.y" {(yyval.val)=newopcall(OPmod,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 59: /* Line 1455 of yacc.c */ #line 152 "../src/language/parse.y" {(yyval.val)=newopcall(OPdr,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 60: /* Line 1455 of yacc.c */ #line 153 "../src/language/parse.y" {(yyval.val)=newopcall(OPeuc,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 61: /* Line 1455 of yacc.c */ #line 154 "../src/language/parse.y" {(yyval.val)=newopcall(OPd,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 62: /* Line 1455 of yacc.c */ #line 155 "../src/language/parse.y" {(yyval.val)=newopcall(OPm,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 63: /* Line 1455 of yacc.c */ #line 156 "../src/language/parse.y" {(yyval.val)=(yyvsp[(2) - (2)].val);;} break; case 64: /* Line 1455 of yacc.c */ #line 157 "../src/language/parse.y" {(yyval.val)=newopcall(OPn,(yyvsp[(2) - (2)].val),-1,&(yyloc));;} break; case 65: /* Line 1455 of yacc.c */ #line 158 "../src/language/parse.y" {(yyval.val)=newopcall(OPpow,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 66: /* Line 1455 of yacc.c */ #line 159 "../src/language/parse.y" {(yyval.val)=newopcall(OPtrans,(yyvsp[(1) - (2)].val),-1,&(yyloc));;} break; case 67: /* Line 1455 of yacc.c */ #line 160 "../src/language/parse.y" {(yyval.val)=newopcall(OPderiv,(yyvsp[(1) - (2)].val),-1,&(yyloc));;} break; case 68: /* Line 1455 of yacc.c */ #line 161 "../src/language/parse.y" {(yyval.val)=newopcall(OPfact,(yyvsp[(1) - (2)].val),-1,&(yyloc));;} break; case 69: /* Line 1455 of yacc.c */ #line 162 "../src/language/parse.y" {(yyval.val)=newnode(Ffacteurmat,(yyvsp[(1) - (2)].val),(yyvsp[(2) - (2)].val),&(yyloc));;} break; case 70: /* Line 1455 of yacc.c */ #line 163 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);;} break; case 71: /* Line 1455 of yacc.c */ #line 164 "../src/language/parse.y" {(yyval.val)=newnode(Ftag,(yyvsp[(1) - (3)].val),0,&(yyloc));;} break; case 72: /* Line 1455 of yacc.c */ #line 165 "../src/language/parse.y" {(yyval.val)=(yyvsp[(2) - (3)].val);;} break; case 73: /* Line 1455 of yacc.c */ #line 168 "../src/language/parse.y" {(yyval.val)=newnode(Fentry,newconst(CSTentry,&(yylsp[(1) - (1)])),-1,&(yyloc));;} break; case 74: /* Line 1455 of yacc.c */ #line 169 "../src/language/parse.y" {(yyval.val)=newnode(Ffacteurmat,(yyvsp[(1) - (2)].val),(yyvsp[(2) - (2)].val),&(yyloc));;} break; case 75: /* Line 1455 of yacc.c */ #line 170 "../src/language/parse.y" {(yyval.val)=newnode(Ftag,(yyvsp[(1) - (3)].val),newconst(CSTentry,&(yylsp[(2) - (3)])),&(yyloc));;} break; case 76: /* Line 1455 of yacc.c */ #line 173 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);;} break; case 77: /* Line 1455 of yacc.c */ #line 174 "../src/language/parse.y" {(yyval.val)=newnode(Fmatrixelts,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 78: /* Line 1455 of yacc.c */ #line 177 "../src/language/parse.y" {(yyval.val)=newnode(Fmatrixlines,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 79: /* Line 1455 of yacc.c */ #line 178 "../src/language/parse.y" {(yyval.val)=newnode(Fmatrixlines,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 80: /* Line 1455 of yacc.c */ #line 181 "../src/language/parse.y" {(yyval.val)=newnode(Fvec,-1,-1,&(yyloc));;} break; case 81: /* Line 1455 of yacc.c */ #line 182 "../src/language/parse.y" {(yyval.val)=newnode(Fmat,-1,-1,&(yyloc));;} break; case 82: /* Line 1455 of yacc.c */ #line 183 "../src/language/parse.y" {(yyval.val)=newnode(Fvec,(yyvsp[(2) - (3)].val),-1,&(yyloc));;} break; case 83: /* Line 1455 of yacc.c */ #line 184 "../src/language/parse.y" {(yyval.val)=newnode(Fmat,(yyvsp[(2) - (3)].val),-1,&(yyloc));;} break; case 84: /* Line 1455 of yacc.c */ #line 185 "../src/language/parse.y" {(yyval.val)=-1; YYABORT;;} break; case 85: /* Line 1455 of yacc.c */ #line 188 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);;} break; case 86: /* Line 1455 of yacc.c */ #line 189 "../src/language/parse.y" {(yyval.val)=newnode(Frefarg,(yyvsp[(2) - (2)].val),-1,&(yyloc));;} break; case 87: /* Line 1455 of yacc.c */ #line 190 "../src/language/parse.y" {if (!pari_once) { yyerrok; } pari_once=1;;} break; case 88: /* Line 1455 of yacc.c */ #line 191 "../src/language/parse.y" {pari_once=0; (yyval.val)=newopcall(OPcat,(yyvsp[(1) - (4)].val),(yyvsp[(4) - (4)].val),&(yyloc));;} break; case 89: /* Line 1455 of yacc.c */ #line 194 "../src/language/parse.y" {(yyval.val)=(yyvsp[(1) - (1)].val);;} break; case 90: /* Line 1455 of yacc.c */ #line 195 "../src/language/parse.y" {(yyval.val)=newnode(Flistarg,(yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 91: /* Line 1455 of yacc.c */ #line 198 "../src/language/parse.y" {(yyval.val)=newnode(Ffunction,newconst(CSTentry,&(yylsp[(1) - (4)])),(yyvsp[(3) - (4)].val),&(yyloc));;} break; case 92: /* Line 1455 of yacc.c */ #line 201 "../src/language/parse.y" {(yyval.val)=newnode(Ffunction,newconst(CSTmember,&(yylsp[(3) - (3)])),(yyvsp[(1) - (3)].val),&(yyloc));;} break; case 93: /* Line 1455 of yacc.c */ #line 205 "../src/language/parse.y" {(yyval.val)=newfunc(CSTentry,&(yylsp[(1) - (6)]),(yyvsp[(3) - (6)].val),(yyvsp[(6) - (6)].val),&(yyloc));;} break; case 94: /* Line 1455 of yacc.c */ #line 207 "../src/language/parse.y" {(yyval.val)=newfunc(CSTmember,&(yylsp[(3) - (5)]),(yyvsp[(1) - (5)].val),(yyvsp[(5) - (5)].val),&(yyloc));;} break; case 95: /* Line 1455 of yacc.c */ #line 208 "../src/language/parse.y" {(yyval.val)=newnode(Flambda, (yyvsp[(1) - (3)].val),(yyvsp[(3) - (3)].val),&(yyloc));;} break; case 96: /* Line 1455 of yacc.c */ #line 209 "../src/language/parse.y" {(yyval.val)=newnode(Flambda, (yyvsp[(2) - (4)].val),(yyvsp[(4) - (4)].val),&(yyloc));;} break; /* Line 1455 of yacc.c */ #line 2473 "../src/language/parse.c" default: break; } 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: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (&yylloc, lex, YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (&yylloc, lex, yymsg); } else { yyerror (&yylloc, lex, YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } yyerror_range[0] = 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[0] = 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 (yyn != YYPACT_NINF) { 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[0] = *yylsp; yydestruct ("Error: popping", yystos[yystate], yyvsp, yylsp, lex); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } *++yyvsp = yylval; yyerror_range[1] = yylloc; /* Using YYLLOC is tempting, but would change the location of the lookahead. YYLOC is available though. */ YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 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) 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 1675 of yacc.c */ #line 212 "../src/language/parse.y" pari-2.5.5/src/language/parsec.h0000644000175000017500000001142612147140047015110 0ustar billbill/* $Id$ 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[]={"_||_", "_&&_", "_===_", "_==_", "_!=_", "_>=_", "_>_", "_<=_", "_<_", "_-_","_+_","_<<_", "_>>_", "_%_", "_\\/_", "_\\_", "_/_", "_*_","_^_","__","_=_","_--","_++","_-=_", "_+=_", "_<<=_", "_>>=_", "_%=_", "_\\/=_", "_\\=_", "_/=_", "_*=_","+_","-_","!_","_!","_'","_~","%","#_","",""}; stack_init(&s_node,sizeof(*pari_tree),(void **)&pari_tree); 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(syntaxer, msg, str, pari_lex_start); } void compile_varerr(const char *str) { pari_err(syntaxer, "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_discarded = 0; 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=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 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(Faffect,name,newnode(Flambda,args,code,loc),loc); } pari-2.5.5/src/language/parse.h0000644000175000017500000000535412147140106014744 0ustar billbill /* A Bison parser, made by GNU Bison 2.4.1. */ /* Skeleton interface for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 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, KPE = 260, KSE = 261, KME = 262, KDE = 263, KDRE = 264, KEUCE = 265, KMODE = 266, KAND = 267, KOR = 268, KID = 269, KEQ = 270, KNE = 271, KGE = 272, KLE = 273, KSRE = 274, KSLE = 275, KSR = 276, KSL = 277, KDR = 278, KPP = 279, KSS = 280, KINTEGER = 281, KREAL = 282, KENTRY = 283, KSTRING = 284, DEFFUNC = 285, SEQ = 286, LVAL = 287, INT = 288, SIGN = 289, MAT = 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.5.5/src/language/members.c0000644000175000017500000002474712147140047015272 0ustar billbill/* $Id$ 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 = lg(x); return (typ(x) == t_VEC && (lx == 6 || lx == 14 || lx == 20)); } INLINE int is_smallell(GEN x) { long lx = lg(x); return (typ(x) == t_VEC && (lx == 14 || lx == 20)); } INLINE int is_ell(GEN x) { long lx = lg(x); return (typ(x) == t_VEC && lx == 20); } static void member_err(const char *s) { pari_err(typeer,s); } GEN member_e(GEN x) { x = get_prid(x); if (!x) member_err("e"); return gel(x,3); } GEN member_f(GEN x) { x = get_prid(x); if (!x) member_err("f"); return gel(x,4); } GEN member_p(GEN x) { long t; (void)get_nf(x,&t); if (t == typ_GAL) return gal_get_p(x); switch(typ(x)) { case t_VEC: x = get_prid(x); if (!x) member_err("p"); return pr_get_p(x); case t_PADIC: return gel(x,2); case t_FFELT: return FF_p_i(x); } member_err("p"); 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"); return NULL; } GEN member_bnf(GEN x) { long t; x = get_bnf(x,&t); if (!x) member_err("bnf"); return x; } 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"); } 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(x[1])); return y; case typ_RNF: return gel(x,7); } member_err("zk"); } 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); } member_err("disc"); } 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 gmael(x,11,1); } if (typ(x)==t_POLMOD) return gel(x,2); if (typ(x)==t_FFELT) return FF_to_FpXQ(x); member_err("pol"); } return nf_get_pol(y); } 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"); } return gel(x,1); } GEN member_sign(GEN x) /* signature */ { long t; GEN y = get_nf(x,&t); if (!y) member_err("sign"); 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) member_err("index"); 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; x = nfmats(get_nf(x,&t)); if (!x) member_err("t2"); return gram_matrix(gel(x,2)); } GEN member_diff(GEN x) /* different */ { long t; x = nfmats(get_nf(x,&t)); if (!x) member_err("diff"); return gel(x,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"); 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_ELL && is_ell(x)) return ell_get_roots(x); if (t == typ_GAL) return gal_get_roots(x); member_err("roots"); } 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); return y; } GEN member_clgp(GEN x) /* class group (3-component row vector) */ { long t; GEN y = get_bnf(x,&t); 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"); } if (t==typ_BNR) return gel(x,5); y = check_RES(y, "clgp"); return gel(y,1); } 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"); } 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"); } 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"); 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"); return NULL; /* not reached */ } GEN member_no(GEN clg) /* number of elements of a group (of type clgp) */ { pari_sp av = avma; clg = member_clgp(clg); if (typ(clg)!=t_VEC || (lg(clg)!=3 && lg(clg)!=4)) member_err("no"); avma = av; return gel(clg,1); } GEN member_cyc(GEN clg) /* cyclic decomposition (SNF) of a group (of type clgp) */ { pari_sp av = avma; clg = member_clgp(clg); if (typ(clg)!=t_VEC || (lg(clg)!=3 && lg(clg)!=4)) member_err("cyc"); avma = av; return gel(clg,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_prid(x); if (y) return mkvec2(gel(y,1), gel(y,2)); (void)get_nf(x,&t); if (t == typ_GAL) return gal_get_gen(x); av = avma; x = member_clgp(x); if (typ(x)!=t_VEC || lg(x)!=4) member_err("gen"); avma = av; if (typ(x[1]) == t_COL) return gel(x,2); /* from bnfisprincipal */ 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); member_err("group"); 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"); return NULL; /* not reached */ } GEN member_a1(GEN x) { if (!is_ell5(x)) member_err("a1"); return ell_get_a1(x); } GEN member_a2(GEN x) { if (!is_ell5(x)) member_err("a2"); return ell_get_a2(x); } GEN member_a3(GEN x) { if (!is_ell5(x)) member_err("a3"); return ell_get_a3(x); } GEN member_a4(GEN x) { if (!is_ell5(x)) member_err("a4"); return ell_get_a4(x); } GEN member_a6(GEN x) { if (!is_ell5(x)) member_err("a6"); return ell_get_a6(x); } GEN member_b2(GEN x) { if (!is_smallell(x)) member_err("b2"); return ell_get_b2(x); } GEN member_b4(GEN x) { if (!is_smallell(x)) member_err("b4"); return ell_get_b4(x); } GEN member_b6(GEN x) { if (!is_smallell(x)) member_err("b6"); return ell_get_b6(x); } GEN member_b8(GEN x) { if (!is_smallell(x)) member_err("b8"); return ell_get_b8(x); } GEN member_c4(GEN x) { if (!is_smallell(x)) member_err("c4"); return ell_get_c4(x); } GEN member_c6(GEN x) { if (!is_smallell(x)) member_err("c6"); return ell_get_c6(x); } GEN member_j(GEN x) { if (!is_smallell(x)) member_err("j"); return ell_get_j(x); } GEN member_omega(GEN x) { if (!is_ell(x)) member_err("omega"); if (!ell_is_real(x)) pari_err(talker,"curve not defined over R"); return mkvec2(gel(x,15), gel(x,16)); } GEN member_eta(GEN x) { if (!is_ell(x)) member_err("eta"); if (!ell_is_real(x)) pari_err(talker,"curve not defined over R"); return mkvec2(gel(x,17), gel(x,18)); } GEN member_area(GEN x) { if (!is_ell(x)) member_err("area"); if (!ell_is_real(x)) pari_err(talker,"curve not defined over R"); return gel(x,19); } GEN member_tate(GEN x) { if (!is_ell(x)) member_err("tate"); if (!ell_is_padic(x)) pari_err(talker,"curve not defined over a p-adic field"); return mkvec3(gel(x,15), gel(x,16), gel(x,17)); } GEN member_w(GEN x) { if (!is_ell(x)) member_err("w"); if (!ell_is_padic(x)) pari_err(talker,"curve not defined over a p-adic field"); return gel(x,18); } pari-2.5.5/src/language/sumiter.c0000644000175000017500000010152212147140047015313 0ustar billbill/* $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. */ #include "pari.h" #include "paripriv.h" #include "anal.h" /********************************************************************/ /** **/ /** ITERATIONS **/ /** **/ /********************************************************************/ void forpari(GEN a, GEN b, GEN code) { pari_sp ltop=avma, av, lim; 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 = typ(a) == t_INT? addis(a, 1): 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(talker, "step equal to zero in forstep"); 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; } /* value changed during the loop, replace by the first prime whose value is strictly larger than new value */ static void update_p(byteptr *ptr, ulong prime[]) { GEN z = get_lex(-1); ulong a, c; if (typ(z) == t_INT) a = 1; else { z = gceil(z); a = 0; } if (lgefint(z) > 3) { prime[2] = ULONG_MAX; /* = infinity */ return; } a += itou(z); c = prime[2]; if (c < a) prime[2] = init_primepointer(a, c, ptr); /* increased */ else if (c > a) { /* lowered, reset p */ *ptr = diffptr; prime[2] = init_primepointer(a, 0, ptr); } set_lex(-1,(GEN)prime); } static byteptr prime_loop_init(GEN ga, GEN gb, ulong *a, ulong *b, ulong *p) { byteptr d = diffptr; ga = gceil(ga); gb = gfloor(gb); if (typ(ga) != t_INT || typ(gb) != t_INT) pari_err(typeer,"prime_loop_init"); if (signe(gb) < 0) return NULL; if (signe(ga) < 0) ga = gen_1; if (lgefint(ga)>3 || lgefint(gb)>3) { if (cmpii(ga, gb) > 0) return NULL; pari_err(primer1, 0); } *a = itou(ga); *b = itou(gb); if (*a > *b) return NULL; maxprime_check(*b); *p = init_primepointer(*a, 0, &d); return d; } void forprime(GEN ga, GEN gb, GEN code) { long p[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3), 0}; ulong *prime = (ulong*)p; ulong a, b; pari_sp av = avma; byteptr d; d = prime_loop_init(ga,gb, &a,&b, (ulong*)&prime[2]); if (!d) { avma = av; return; } avma = av; push_lex((GEN)prime,code); while (prime[2] < b) { closure_evalvoid(code); if (loop_break()) break; if (get_lex(-1) == (GEN) prime) NEXT_PRIME_VIADIFF(prime[2], d); else update_p(&d, prime); avma = av; } /* if b = P --> *d = 0 now and the loop wouldn't end if it read 'while * (prime[2] <= b)' */ if (prime[2] == b) { closure_evalvoid(code); (void)loop_break(); avma = av; } pop_lex(1); } 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 forvec_next_i(GEN gd, GEN ignored) { forvec_data *d=(forvec_data *) gd; long i = d->n; (void)ignored; 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 forvec_next(GEN gd, GEN v) { forvec_data *d=(forvec_data *) gd; long i = d->n; for (;;) { gel(v,i) = gaddgs(gel(v,i), 1); if (gcmp(gel(v,i), d->M[i]) <= 0) return v; gel(v,i) = d->m[i]; if (--i <= 0) return NULL; } } /* non-decreasing order [over integers] */ static GEN forvec_next_le_i(GEN gd, GEN ignored) { forvec_data *d=(forvec_data *) gd; long i = d->n; (void)ignored; 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 forvec_next_le(GEN gd, GEN v) { forvec_data *d=(forvec_data *) gd; long i = d->n, imin = d->n; for (;;) { gel(v,i) = gaddgs(gel(v,i), 1); if (gcmp(gel(v,i), d->M[i]) <= 0) { while (i < d->n) { i++; if (gcmp(gel(v,i-1), gel(v,i)) <= 0) continue; while (gcmp(gel(v,i-1), d->M[i]) > 0) { i = imin - 1; if (!i) return NULL; imin = i; gel(v,i) = gaddgs(gel(v,i), 1); if (gcmp(gel(v,i), d->M[i]) <= 0) break; } if (i > 1) { /* a >= a[i-1] - a[i] */ GEN a = gceil(gsub(gel(v,i-1), gel(v,i))); gel(v,i) = gadd(gel(v,i), a); } } return v; } gel(v,i) = d->m[i]; if (--i <= 0) return NULL; if (i < imin) imin = i; } } /* strictly increasing order [over integers] */ static GEN forvec_next_lt_i(GEN gd, GEN ignored) { forvec_data *d=(forvec_data *) gd; long i = d->n; (void)ignored; 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 forvec_next_lt(GEN gd, GEN v) { forvec_data *d=(forvec_data *) gd; long i = d->n, imin = d->n; for (;;) { gel(v,i) = gaddgs(gel(v,i), 1); if (gcmp(gel(v,i), d->M[i]) <= 0) { while (i < d->n) { i++; if (gcmp(gel(v,i-1), gel(v,i)) < 0) continue; for(;;) { GEN a, b; a = addis(gfloor(gsub(gel(v,i-1), gel(v,i))), 1); /* a> v[i-1]-v[i] */ b = gadd(gel(v,i), a); /* v[i-1] < b <= v[i-1] + 1 */ if (gcmp(b, d->M[i]) <= 0) { gel(v,i) = b; break; } for (; i >= imin; i--) gel(v,i) = d->m[i]; if (!i) return NULL; imin = i; gel(v,i) = gaddgs(gel(v,i), 1); if (gcmp(gel(v,i), d->M[i]) <= 0) break; } } return v; } gel(v,i) = d->m[i]; if (--i <= 0) return NULL; if (i < imin) imin = i; } } /* 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] */ GEN forvec_start(GEN x, long flag, GEN *gd, GEN (**next)(GEN,GEN)) { long i, tx = typ(x), l = lg(x), t = t_INT; forvec_data *d; if (!is_vec_t(tx)) pari_err(talker,"not a vector in forvec"); if (l == 1) { *next = &forvec_dummy; return cgetg(1, tx); } *gd = cgetg(sizeof(forvec_data)/sizeof(long) + 1, t_VECSMALL) + 1; d = (forvec_data*) *gd; d->n = l - 1; d->a = (GEN*)cgetg(l,tx); d->m = (GEN*)cgetg(l,tx); d->M = (GEN*)cgetg(l,tx); 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(talker,"not a vector of two-component vectors in forvec"); 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(typeer,"forvec"); 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(typeer,"forvec"); 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) return (GEN)NULL; 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(typeer,"forvec"); 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(typeer,"forvec"); 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: *next = t==t_INT? &forvec_next_i: &forvec_next; break; case 1: *next = t==t_INT? &forvec_next_le_i: &forvec_next_le; break; case 2: *next = t==t_INT? &forvec_next_lt_i: &forvec_next_lt; break; default: pari_err(flagerr,"forvec"); } return (GEN)d->a; } void forvec(GEN x, GEN code, long flag) { pari_sp av = avma; GEN (*next)(GEN,GEN); GEN D, v = forvec_start(x, flag, &D, &next); push_lex(v,code); while (v) { closure_evalvoid(code); if (loop_break()) break; v = next(D, v); } 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(talker,"non integral index in sum"); 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(talker,"non integral index in suminf"); a = setloop(a); av = avma; lim = stack_lim(av,1); fl=0; G = bit_accuracy(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 divsum(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(talker,"non integral index in prodinf"); a = setloop(a); av = avma; lim = stack_lim(av,1); fl=0; G = -bit_accuracy(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(talker,"non integral index in prodinf1"); a = setloop(a); av = avma; lim = stack_lim(av,1); fl=0; G = -bit_accuracy(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(flagerr); return NULL; /* not reached */ } GEN prodeuler(void *E, GEN (*eval)(void *, GEN), GEN ga, GEN gb, long prec) { long p[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3), 0}; ulong a, b; pari_sp av, av0 = avma, lim; GEN prime = p, x = real_1(prec); byteptr d; av = avma; d = prime_loop_init(ga,gb, &a,&b, (ulong*)&prime[2]); if (!d) { avma = av; return x; } av = avma; lim = stack_lim(avma,1); while ((ulong)prime[2] < b) { 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); } NEXT_PRIME_VIADIFF(prime[2], d); } if ((ulong)prime[2] == b) x = gmul(x, eval(E, prime)); return gerepilecopy(av0,x); } GEN prodeuler0(GEN a, GEN b, GEN code, long prec) { EXPR_WRAP(code, prodeuler(EXPR_ARG, a, b, prec)); } GEN direuler(void *E, GEN (*eval)(void *, GEN), GEN ga, GEN gb, GEN c) { long pp[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3), 0}; ulong a, b, i, k, n, p; pari_sp av0 = avma, av, lim = stack_lim(av0, 1); long j, tx, lx; GEN x, y, s, polnum, polden, prime = pp; byteptr d; d = prime_loop_init(ga,gb, &a,&b, (ulong*)&prime[2]); n = c? itou(c): b; if (!d || b < 2 || (c && signe(c) < 0)) return mkvec(gen_1); if (n < b) b = n; y = cgetg(n+1,t_VEC); av = avma; x = zerovec(n); gel(x,1) = gen_1; p = prime[2]; while (p <= b) { s = eval(E, prime); polnum = numer(s); polden = denom(s); tx = typ(polnum); if (is_scalar_t(tx)) { if (!gequal1(polnum)) { if (!gequalm1(polnum)) pari_err(talker,"constant term != 1 in direuler"); polden = gneg(polden); } } else { ulong k1, q, qlim; if (tx != t_POL) pari_err(typeer,"direuler"); lx = degpol(polnum); if (lx < 0) pari_err(talker,"constant term != 1 in direuler"); c = gel(polnum,2); if (!gequal1(c)) { if (!gequalm1(c)) pari_err(talker,"constant term != 1 in direuler"); polnum = gneg(polnum); polden = gneg(polden); } for (i=1; i<=n; i++) y[i]=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(talker,"constant term != 1 in direuler"); } else { if (tx != t_POL) pari_err(typeer,"direuler"); c = gel(polden,2); if (!gequal1(c)) pari_err(talker,"constant term != 1 in direuler"); 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); } NEXT_PRIME_VIADIFF(p, d); prime[2] = p; } 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 vecteur(GEN nmax, GEN code) { GEN y,p1; long i,m; long c[]={evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3), 0}; m = gtos(nmax); if (m < 0) pari_err(talker,"negative number of components in vector"); 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; long c[]={evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3), 0}; m = gtos(nmax); if (m < 0) pari_err(talker,"negative number of components in vector"); if (!code) return const_vecsmall(m, 0); 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; long c1[]={evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3), 1}; long c2[]={evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3), 1}; m = gtos(ncol); n = gtos(nlig); if (m < 0) pari_err(talker,"negative number of columns in matrix"); if (n < 0) pari_err(talker,"negative number of rows in matrix"); 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; j>1,prec+1); pol = RgX_div_by_X_x(pol, gen_1, &dn); N = degpol(pol); s = gen_0; for (k=0; k<=N; k++) { s = gadd(s, gmul(gel(pol,k+2), eval(E, a))); if (k == N) break; a = addsi(1,a); } 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(flagerr); } 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(talker,"non integral index in sumpos"); a = subis(a,1); reel = cgetr(prec); e1 = addsr(3, sqrtr(stor(8,prec))); N = (long)(0.4*(bit_accuracy(prec) + 7)); d = powru(e1,N); d = shiftr(addrr(d, invr(d)),-1); az = gen_m1; c = d; s = gen_0; G = -bit_accuracy(prec) - 5; stock = (GEN*)new_chunk(N+1); for (k=1; k<=N; k++) stock[k] = NULL; for (k=0; k>1,prec+1); 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(flagerr); } 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,tol1,min1,min2,fa,fb,fc,p,q,r,s,xm; 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(talker,"roots must be bracketed in solve"); itmax = (prec * (2*BITS_IN_LONG)) + 1; tol = real2n(5-bit_accuracy(prec), 3); fc = fb; e = d = NULL; /* gcc -Wall */ for (iter=1; iter<=itmax; iter++) { 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 = mulrr(tol, gmax(tol,absr(b))); xm = shiftr(subrr(c,b),-1); if (cmprr(absr(xm),tol1) <= 0 || gequal0(fb)) break; /* SUCCESS */ if (cmprr(absr(e),tol1) >= 0 && gcmp(gabs(fa,0),gabs(fb,0)) > 0) { /* attempt interpolation */ s = gdiv(fb,fa); if (cmprr(a,c)==0) { p = gmul2n(gmul(xm,s),1); q = gsubsg(1,s); } else { q = gdiv(fa,fc); r = gdiv(fb,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(talker,"too many iterations in solve"); 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 fpr, pr, l, e, ex; pari_sp av = avma; fpr = precision(x)-2; /* required final prec (in sig. words) */ if (fpr == -2) fpr = prec-2; ex = gexpo(x); if (ex < 0) ex = 0; /* near 0 */ pr = (long)ceil(fpr * 1.5 + (ex / BITS_IN_LONG)); l = 2+pr; switch(typ(x)) { case t_REAL: case t_COMPLEX: x = gprec_w(x, l + 1 + (ex / BITS_IN_LONG)); } e = fpr * (BITS_IN_LONG/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, fpr+2)); } 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(typeer, "formal derivation"); 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.5.5/src/language/init.h0000644000175000017500000033011312201011602014554 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,NULL,13,NULL,"+_"}, {"-_",0,(void*)gneg,13,"G","-_"}, {"Col",0,(void*)gtocol,2,"DG","Col({x=[]}): transforms the object x into a column vector. 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(x,y): creates 'x modulo y'."}, {"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(x,{v=x}): convert x (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(x,{v=x}): convert x (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*)gtovec,2,"DG","Vec({x=[]}): transforms the object x into a vector. Empty vector if x is omitted."}, {"Vecrev",0,(void*)gtovecrev,2,"DG","Vecrev({x=[]}): transforms the object x into a vector. Empty vector if x is omitted."}, {"Vecsmall",0,(void*)gtovecsmall,2,"DG","Vecsmall({x=[]}): transforms the object x into a VECSMALL. Empty vector if x is omitted."}, {"_!",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"}, {"_.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"}, {"_.w",0,(void*)member_w,14,"mG","_.w"}, {"_.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","_>=_"}, {"_>>=_",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","_>_"}, {"_\\/=_",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"}, {"_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*)gach,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 -pi0. 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."}, {"bnfisprincipal",0,(void*)bnfisprincipal0,6,"GGD1,L,","bnfisprincipal(bnf,x,{flag=1}): bnf being output by bnfinit (with flag<=2), gives [v,alpha], where v is the vector of exponents on the class group generators and alpha is the generator of the resulting principal ideal. In particular x is principal if and only if v is the zero vector. flag is optional, whose binary digits mean 1: output [v,alpha] (only v if unset); 2: increase precision until alpha can be computed (do not insist if unset)."}, {"bnfissunit",0,(void*)bnfissunit,6,"GGG","bnfissunit(bnf,sfu,x): bnf being output by bnfinit (with flag<=2), sfu by bnfsunit, gives the column vector of exponents of x on the fundamental S-units and the roots of unity if x is a unit, the empty vector otherwise."}, {"bnfisunit",0,(void*)bnfisunit,6,"GG","bnfisunit(bnf,x): bnf being output by bnfinit, gives the column vector of exponents of x on the fundamental units and the roots of unity if x is a unit, the empty vector otherwise."}, {"bnfnarrow",0,(void*)buchnarrow,6,"G","bnfnarrow(bnf): given a big number field as output by bnfinit, gives as a 3-component vector the structure of the narrow class group."}, {"bnfsignunit",0,(void*)signunits,6,"G","bnfsignunit(bnf): matrix of signs of the real embeddings of the system of fundamental units found by bnfinit."}, {"bnfsunit",0,(void*)bnfsunit,6,"GGp","bnfsunit(bnf,S): compute the fundamental S-units of the number field bnf output by bnfinit, S being a list of prime ideals. res[1] contains the S-units, res[5] the S-classgroup. See manual for details."}, {"bnrL1",0,(void*)bnrL1,6,"GDGD0,L,p","bnrL1(bnr, {subgrp}, {flag=0}): bnr being output by bnrinit(,,1) and subgrp 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."}, {"bnrclassno",0,(void*)bnrclassno,6,"GG","bnrclassno(bnf,I): ray class number of the module I for the big number field bnf. Faster than bnrinit if only the ray class number is wanted."}, {"bnrclassnolist",0,(void*)bnrclassnolist,6,"GG","bnrclassnolist(bnf,list): if list is as output by ideallist or similar, gives list of corresponding ray class numbers."}, {"bnrconductor",0,(void*)bnrconductor0,6,"GDGDGD0,L,","bnrconductor(A,{B},{C},{flag=0}): conductor f of the subfield of the ray class field given by A,B,C. flag is optional and can be 0: default, 1: returns [f, Cl_f, H], H subgroup of the ray class group modulo f defining the extension, 2: returns [f, bnr(f), H]."}, {"bnrconductorofchar",0,(void*)bnrconductorofchar,6,"GG","bnrconductorofchar(bnr,chi): conductor of the character chi on the ray class group bnr."}, {"bnrdisc",0,(void*)bnrdisc0,6,"GDGDGD0,L,","bnrdisc(A,{B},{C},{flag=0}): absolute or relative [N,R1,discf] of the field defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf, modulus] or [bnf,modulus,subgroup], where bnf is as output by bnfinit, bnr by bnrinit, and subgroup is the HNF matrix of a subgroup of the corresponding ray class group (if omitted, the trivial subgroup). flag is optional whose binary digits mean 1: give relative data; 2: return 0 if modulus is not the conductor."}, {"bnrdisclist",0,(void*)bnrdisclist0,6,"GGDG","bnrdisclist(bnf,bound,{arch}): gives list of discriminants of ray class fields of all conductors up to norm bound, in a long vector The ramified Archimedean places are given by arch; all possible values are taken if arch is omitted. Supports the alternative syntax bnrdisclist(bnf,list), where list is as output by ideallist or ideallistarch (with units)."}, {"bnrinit",0,(void*)bnrinit0,6,"GGD0,L,","bnrinit(bnf,f,{flag=0}): given a bnf as output by bnfinit and a modulus f, initializes data linked to the ray class group structure corresponding to this module. flag is optional, and can be 0: default, 1: compute also the generators."}, {"bnrisconductor",0,(void*)bnrisconductor0,6,"lGDGDG","bnrisconductor(A,{B},{C}): returns 1 if the modulus is the conductor of the subfield of the ray class field given by A,B,C (see bnrdisc), and 0 otherwise. Slightly faster than bnrconductor if this is the only desired result."}, {"bnrisprincipal",0,(void*)bnrisprincipal,6,"GGD1,L,","bnrisprincipal(bnr,x,{flag=1}): bnr being output by bnrinit, gives [v,alpha], where v is the vector of exponents on the class group generators and alpha is the generator of the resulting principal ideal. In particular x is principal if and only if v is the zero vector. If (optional) flag is set to 0, output only v."}, {"bnrrootnumber",0,(void*)bnrrootnumber,6,"GGD0,L,p","bnrrootnumber(bnr,chi,{flag=0}): returns the so-called Artin Root Number, i.e. the constant W appearing in the functional equation of the Hecke L-function associated to chi. Set flag = 1 if the character is known to be primitive."}, {"bnrstark",0,(void*)bnrstark,6,"GDGp","bnrstark(bnr,{subgroup}): bnr being as output by bnrinit(,,1), finds a relative equation for the class field corresponding to the module in bnr and the given congruence subgroup (the trivial subgroup if omitted) using Stark's units. The ground field and the class field must be totally real."}, {"break",0,(void*)break0,11,"D1,L,","break({n=1}): interrupt execution of current instruction sequence, and exit from the n innermost enclosing loops."}, {"ceil",0,(void*)gceil,2,"G","ceil(x): ceiling of x = smallest integer >= x."}, {"centerlift",0,(void*)centerlift0,2,"GDn","centerlift(x,{v}): centered lift of x. Same as lift except for integermods."}, {"charpoly",0,(void*)charpoly0,8,"GDnD3,L,","charpoly(A,{v=x},{flag=3}): 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) or 2 (use Hessenberg form), 3 (Berkowitz, default). All algorithms except flag = 3 (Berkowitz) 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."}, {"component",0,(void*)compo,2,"GL","component(x,n): the n'th component of the internal representation of x. For vectors or matrices, it is simpler to use x[]. For list objects such as nf, bnf, bnr or ell, it is much easier to use member functions starting with \".\"."}, {"concat",0,(void*)concat,8,"GDG","concat(x,{y}): concatenation of x and y, which can be scalars, vectors or matrices, or lists (in this last case, both x and y have to be lists). If y is omitted, x has to be a list or row vector and its elements are concatenated."}, {"conj",0,(void*)gconj,2,"G","conj(x): the algebraic conjugate of x."}, {"conjvec",0,(void*)conjvec,2,"Gp","conjvec(z): conjugate vector of the algebraic number z."}, {"content",0,(void*)content,4,"G","content(x): gcd of all the components of x, when this makes sense."}, {"contfrac",0,(void*)contfrac0,4,"GDGD0,L,","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."}, {"contfracpnqn",0,(void*)pnqn,4,"G","contfracpnqn(x): [p_n,p_{n-1}; q_n,q_{n-1}] corresponding to the continued fraction x."}, {"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*)gch,3,"Gp","cosh(x): hyperbolic cosine of x."}, {"cotan",0,(void*)gcotan,3,"Gp","cotan(x): cotangent of x."}, {"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."}, {"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, computes the vector of the first n values of the exponential integral E1(n.x) (x > 0)."}, {"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*)addell,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 a minimal 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 a_p for the elliptic curve E using Shanks-Mestre's method, or SEA algorithm if the package seadata is installed. Assume the equation is minimal at p."}, {"ellbil",0,(void*)bilhell,5,"GGGp","ellbil(E,z1,z2): canonical bilinear form for the points z1,z2 on the elliptic curve E (assumed to be minimal). Either z1 or z2 can also be a vector/matrix of points."}, {"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]."}, {"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 for the curve E in the variable v."}, {"elleisnum",0,(void*)elleisnum,5,"GLD0,L,p","elleisnum(E,k,{flag=0}): E being an elliptic curve (or, alternatively, given by a 2-component vector representing its periods) and k an even positive integer, computes the numerical value of the Eisenstein series of weight k. When flag is non-zero and k=4 or 6, this gives g2 or g3 with the correct normalization."}, {"elleta",0,(void*)elleta,5,"Gp","elleta(om): om=[om1,om2], returns the two-component row vector [eta1,eta2] of quasi-periods associated to [om1,om2]."}, {"ellgenerators",0,(void*)ellgenerators,5,"G","ellgenerators(E): if E is an elliptic curve as output by ellinit(), return the generators of the Mordell-Weil group associated to the curve. This function depends on the curve being referenced in the elldata database."}, {"ellglobalred",0,(void*)ellglobalred,5,"G","ellglobalred(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."}, {"ellgroup",0,(void*)ellgroup,5,"GDG","ellgroup(E,{p}): computes the structure of the group E(Fp) Assume the equation is minimal at p."}, {"ellheight",0,(void*)ellheight0,5,"GGD2,L,p","ellheight(E,x,{flag=2}): canonical height of point x on elliptic curve E (assumed to be a minimal model). 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, assume to be a minimal model."}, {"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 J. E. Cremona database, M the minimal model and C the coordinates change (see ellchangecurve)."}, {"ellinit",0,(void*)ellinit0,5,"GD0,L,p","ellinit(x,{flag=0}): x being the vector [a1,a2,a3,a4,a6] defining the curve Y^2 + a1.XY + a3.Y = X^3 + a2.X^2 + a4.X + a6, gives the vector: [a1,a2,a3,a4,a6,b2,b4,b6,b8,c4,c6,disc,j,[e1,e2,e3],w1,w2,eta1,eta2,area]. If the curve is defined over a p-adic field, the last six components are replaced by root,u^2,u,q,w,0. If optional flag is 1, omit them altogether. x can also be a string, in this case the coefficients of the curve with matching name are looked in the elldata database if available."}, {"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(l,{x},{y}): return a vector [eqn, t] where eqn is a modular equation of level l, for l<500, l prime. This requires the package seadata to be installed. The equation is either of canonical type (t=0) or of Atkin type (t=1)"}, {"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 (mandatory over non-prime finite fields)."}, {"ellordinate",0,(void*)ellordinate,5,"GGp","ellordinate(E,x): y-coordinates corresponding to x-ordinate x on elliptic curve E."}, {"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*)powell,5,"GGG","ellpow(E,z,n): n times the point z on elliptic curve E (n in Z)."}, {"ellrootno",0,(void*)ellrootno,5,"lGDG","ellrootno(E,{p=1}): root number for the L-function of the elliptic curve E. p can be 1 (default), global root number, or a prime p (including 0) for the local root number at p."}, {"ellsearch",0,(void*)ellsearch,5,"G","ellsearch(N): if N is an integer, it is taken as a conductor else if N is a string, it can be a curve name (\"11a1\"), a isogeny class (\"11a\") or a conductor (\"11\"). Return all curves in the elldata database that match the property."}, {"ellsigma",0,(void*)ellsigma,5,"GGD0,L,p","ellsigma(E,z,{flag=0}): E being given by ellinit, returns the value of the Weierstrass sigma function of the lattice generated by om at z if flag = 0 (default). If flag = 1, arbitrary determination of the logarithm of sigma. If flag = 2 or 3, same but using the product expansion instead of theta series."}, {"ellsub",0,(void*)subell,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 (minimal model)."}, {"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 Doud's algorithm; if flag = 1, use Lutz-Nagell."}, {"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,DPp","ellwp(E,{z=x},{flag=0},{d=seriesprecision}): computes the value at z of the Weierstrass P function attached to the elliptic curve E as given by ellinit (alternatively, E can be given as a lattice [om1,om2]). Optional flag means 0 (default), compute only P(z), 1 compute [P(z),P'(z)], 2 consider om as an elliptic curve and compute P(z) for that curve (identical to ellztopoint in that case). If z is omitted or is a simple variable, return formal expansion in z with d significant terms."}, {"ellzeta",0,(void*)ellzeta,5,"GGp","ellzeta(E,z): E being given by ellinit, returns the value at z of the Weierstrass zeta function of the period lattice of E."}, {"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."}, {"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*)geulerphi,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."}, {"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 (up to primelimit if lim=0)."}, {"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,{flag=0}): p-adic factorization of the polynomial pol to precision r. flag is optional and may be set to 0 (use round 4) or 1 (use Buchmann-Lenstra)."}, {"ffgen",0,(void*)ffgen,4,"GDn","ffgen(P,{v}): return the generator g=X mod P(X) of the finite field defined by the polynomial P(X). 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."}, {"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."}, {"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."}, {"forprime",0,(void*)forprime,11,"vV=GGI","forprime(X=a,b,seq): the sequence is evaluated, X running over the primes between a and 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 (in SNF form), whose index is bounded by bound. 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 neccessary informations 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 x, s a complex or p-adic number."}, {"gammah",0,(void*)ggamd,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."}, {"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."}, {"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,a,{b}): hermite normal form of the ideal a in the number field nf. If called as idealhnf(nf,a,b), the ideal is given as aZ_K+bZ_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."}, {"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."}, {"idealramgroups",0,(void*)idealramgroups,6,"GGG","idealramgroups(nf,gal,pr): let pr be a prime ideal pr in prid format, in the Galois group gal 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."}, {"imag",0,(void*)gimag,2,"G","imag(x): imaginary part of x."}, {"incgam",0,(void*)incgam0,3,"GGDGp","incgam(s,x,{y}): incomplete gamma function. y is optional and is the precomputed value of gamma(s)."}, {"incgamc",0,(void*)incgamc,3,"GGp","incgamc(s,x): complementary incomplete gamma function."}, {"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*)gisfundamental,4,"G","isfundamental(x): true(1) if x is a fundamental discriminant (including 1), false(0) if not."}, {"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."}, {"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."}, {"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*)gissquareall,4,"GD&","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*)gissquarefree,4,"G","issquarefree(x): true(1) if x is squarefree, false(0) if not."}, {"kill",0,(void*)kill0,11,"vr","kill(sym): restores the symbol sym to its ``undefined'' status and kill associated help messages."}, {"kronecker",0,(void*)gkronecker,4,"GG","kronecker(x,y): kronecker symbol (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=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): Gaussian 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*)gmoebius,4,"G","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*)gnextprime,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*)nfbasis0,6,"GD0,L,DG","nfbasis(x,{flag=0},{fa}): integral basis of the field Q[a], where a is a root of the polynomial x, using the round 4 algorithm. Second and third args are optional. Binary digits of flag mean 1: assume that no square of a prime>primelimit divides the discriminant of x, 2: use round 2 algorithm instead. If present, fa provides the matrix of a partial factorization of the discriminant of x, useful if one wants only an order maximal at certain primes only."}, {"nfbasistoalg",0,(void*)basistoalg,6,"GG","nfbasistoalg(nf,x): transforms the column vector x on the integral basis into an algebraic number."}, {"nfdetint",0,(void*)nfdetint,6,"GG","nfdetint(nf,x): multiple of the ideal determinant of the pseudo generating set x."}, {"nfdisc",0,(void*)nfdisc0,6,"GD0,L,DG","nfdisc(x,{flag=0},{fa}): discriminant of the number field defined by the polynomial x using round 4. Optional args flag and fa are as in nfbasis."}, {"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,x): factor polynomial x 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,pol,pr): factorize polynomial pol 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,pr): solution of a*x=b in Z_K/pr, where a is a matrix and b a column vector, and where pr 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,2,"G","norml2(x): square of the L2-norm of the vector x."}, {"numbpart",0,(void*)numbpart,4,"G","numbpart(n): number of partitions of n."}, {"numdiv",0,(void*)gnumbdiv,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*)gomega,4,"G","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."}, {"partitions",0,(void*)partitions,4,"LD0,L,","partitions(n,{restr=0}): return vector of partitions of n, a positive integer. The second optional argument may be set to a number smaller than n to restrict the value of each element in the partitions to that value. The default of 0 means that this maximum is n itself."}, {"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."}, {"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(x): Galois group of the polynomial x (see manual for group coding). Return [n, s, k, name] where n is the order, s the signature, k the index and name is the GAP4 name of the transitive group."}, {"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."}, {"polisirreducible",0,(void*)gisirreducible,7,"G","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(x,{flag=0},{fa}): reduction of the polynomial x (gives minimal polynomials only). Second and third args are optional. The following binary digits of flag are significant 1: partial reduction, 2: gives also elements. fa, if present, contains the factorization matrix of the discriminant."}, {"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)). 16: partial reduction."}, {"polredord",0,(void*)ordred,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)."}, {"polroots",0,(void*)roots0,7,"GD0,L,p","polroots(x,{flag=0}): complex roots of the polynomial x. flag is optional, and can be 0: default, uses Schonhage's method modified by Gourdon, or 1: uses a modified Newton method."}, {"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 is 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}): Tchebitcheff polynomial of degree n, in variable v. (For backward compatibility.)"}, {"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}): change the precision of x to be n. If n is omitted, output real precision of object x."}, {"precprime",0,(void*)gprecprime,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*)primes,4,"L","primes(x): returns the vector of the first x primes."}, {"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."}, {"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."}, {"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."}, {"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)."}, {"qfjacobi",0,(void*)jacobi,8,"Gp","qfjacobi(x): eigenvalues and orthogonal matrix of eigenvectors of the real symmetric matrix x."}, {"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."}, {"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. Binary digits of flag mean 1: count vectors of even norm from 1 to 2B, 2: return a t_VECSMALL instead of a t_VEC."}, {"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)."}, {"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,"GGD0,L,","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*)rnfelementabstorel,6,"GG","rnfeltabstorel(rnf,x): transforms the element x from absolute to relative representation."}, {"rnfeltdown",0,(void*)rnfelementdown,6,"GG","rnfeltdown(rnf,x): expresses x on the base field if possible; returns an error otherwise."}, {"rnfeltreltoabs",0,(void*)rnfelementreltoabs,6,"GG","rnfeltreltoabs(rnf,x): transforms the element x from relative to absolute representation."}, {"rnfeltup",0,(void*)rnfelementup,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 the absolute equation apol of the number field defined by pol. flag is optional, and can be 0: default, or non-zero, gives [apol,th], where th expresses the root of nf.pol in terms of the root of apol."}, {"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*)rnfidealhermite,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 a non constant 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."}, {"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,"GG","select(f, A): selects elements of A according to the selection function f."}, {"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*)recip,7,"G","serreverse(x): reversion of the power series x."}, {"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}): looks if x belongs to the set S. If flag is 0 or omitted, returns 0 if it is 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*)gsumdivk,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*)gsh,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 (x 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."}, {"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"}, {"sumdiv",0,(void*)divsum,9,"GVE","sumdiv(n,X,expr): sum of expression expr, X running over the divisors of n."}, {"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*)gth,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."}, {"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 unconditionnaly. 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 ommitted); sequence rec is executed if the error occurs and is the result of the command."}, {"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."}, {"until",0,(void*)untilpari,11,"vEI","until(a,seq): evaluate the expression sequence seq until a is nonzero."}, {"valuation",0,(void*)ggval,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, error for scalars. 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*)vecmax,1,"G","vecmax(x): maximum of the elements of the vector/matrix x"}, {"vecmin",0,(void*)vecmin,1,"G","vecmin(x): minimum of the elements of the vector/matrix x"}, {"vecsort",0,(void*)vecsort0,8,"GDGD0,L,","vecsort(x,{cmp},{flag=0}): sorts the vector of vectors (or matrix) x in ascending order, according to the comparison function cmp, if not omitted. (If cmp 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."}, {"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. If no o is given, assume that g generate (Z/nZ)*."}, {"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*)znprimroot0,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.5.5/src/language/compile.c0000644000175000017500000013412412147140046015256 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 */ 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) { stack_init(&s_opcode,sizeof(*opcode),(void **)&opcode); stack_init(&s_operand,sizeof(*operand),(void **)&operand); stack_init(&s_data,sizeof(*data),(void **)&data); stack_init(&s_lvar,sizeof(*localvars),(void **)&localvars); stack_init(&s_dbginfo,sizeof(*dbginfo),(void **)&dbginfo); stack_init(&s_frame,sizeof(*frames),(void **)&frames); offset=-1; } void pari_close_compiler(void) { stack_delete(&s_opcode); stack_delete(&s_operand); stack_delete(&s_data); 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(struct codepos *pos, long arity, long nbmvar, GEN text) { 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; } 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; s_lvar.n=pos->localvars; 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); } static void op_push_loc(op_code o, long x, const char *loc) { long n=stack_new(&s_opcode); long m=stack_new(&s_operand); long d=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=stack_new(&s_opcode); (void) stack_new(&s_operand); (void) 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=stack_new(&s_data); data[n] = x?gclone(x):x; return n-offset; } static void var_push(entree *ep, Ltype type) { long n=stack_new(&s_lvar); localvars[n].ep = ep; localvars[n].type = type; } static void frame_push(GEN x) { long n=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) { char *code=GSTR(gel(C,2))-1; GEN oper=gel(C,3); GEN frpc=gmael(C,5,2); GEN fram=gmael(C,5,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: -- FLreturn: 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, FLnocopy=2, FLnocopylex=4}; static void copyifclone(long n, long mode, long flag, long mask) { if (mode==Ggen && !(flag&mask)) { op_push(OCcopyifclone,0,n); if (!(flag&FLreturn) && 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 '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 '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(bugparier,"compilecast, type unknown %ld",mode); } } 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; i0; 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); } static entree * getlvalue(long n) { while (tree[n].f==Ffacteurmat || tree[n].f==Ftag) n=tree[n].x; return getvar(n); } static void compilelvalue(long n) { n = detag(n); if (tree[n].f==Fentry) return; else { long x=tree[n].x; long y=tree[n].y; long yx=tree[y].x; long yy=tree[y].y; long f=tree[y].f; if (tree[x].f==Ffacteurmat && f==Fmatrix && yy==-1 && tree[tree[x].y].f==FmatrixL) { compilelvalue(tree[x].x); compilenode(tree[tree[x].y].x,Gsmall,0); compilenode(yx,Gsmall,0); op_push(OCcompo2ptr,0,y); return; } compilelvalue(x); compilenode(yx,Gsmall,0); if (f==Fmatrix && yy==-1) op_push(OCcompo1ptr,0,y); else { switch(f) { case Fmatrix: compilenode(yy,Gsmall,0); op_push(OCcompo2ptr,0,y); break; case FmatrixR: op_push(OCcompoCptr,0,y); break; case FmatrixL: op_push(OCcompoLptr,0,y); break; } } } } static void compilefacteurmat(long n, int mode) { long x=tree[n].x; long y=tree[n].y; long yx=tree[y].x; long yy=tree[y].y; long f=tree[y].f; compilenode(x,Ggen,FLnocopy); compilenode(yx,Gsmall,0); if (f==Fmatrix && yy==-1) { op_push(OCcompo1,mode,y); return; } switch(f) { case Fmatrix: compilenode(yy,Gsmall,0); op_push(OCcompo2,mode,y); return; case FmatrixR: op_push(OCcompoC,0,y); compilecast(n,Gvec,mode); return; case FmatrixL: op_push(OCcompoL,0,y); compilecast(n,Gvec,mode); return; default: pari_err(bugparier,"compilefacteurmat"); } } 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 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=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==Faffect) { nb=2; lnc=2; lnl=2; arg=mkvecsmall2(x,y); } else if (is_func_named(x,"if") && mode==Gvoid) ep=is_entry("_void_if"); else if (is_func_named(x,"my")) { long lgarg; GEN vep = cgetg_copy(arg, &lgarg); if (nb) { long i; for(i=1;i<=nb;i++) { long a=arg[i]; vep[i]=(long)getvar(tree[a].f==Faffect?tree[a].x:a); var_push(NULL,Lmy); } checkdups(arg,vep); op_push_loc(OCnewframe,nb,str); frame_push(vep); for (i=1;i<=nb;i++) { long a=arg[i]; if (tree[a].f==Faffect && !is_node_zero(tree[a].y)) { compilenode(tree[a].y,Ggen,FLnocopy); op_push(OCstorelex,-nb+i-1,a); } localvars[s_lvar.n-nb+i-1].ep=(entree*)vep[i]; } } compilecast(n,Gvoid,mode); avma=ltop; return; } else if (is_func_named(x,"local")) { long lgarg; long i; GEN vep = cgetg_copy(arg, &lgarg); for (i=1;i<=nb;i++) { entree *en; long a=arg[i]; op_code op=OClocalvar0; if (tree[a].f==Faffect) { if (!is_node_zero(tree[a].y)) { compilenode(tree[a].y,Ggen,FLnocopy); op=OClocalvar; } a=tree[a].x; } vep[i] = (long) (en = getvar(a)); op_push(op,vep[i],a); var_push(en,Llocal); } checkdups(arg,vep); compilecast(n,Gvoid,mode); avma=ltop; return; } /*We generate dummy code for global() for compatibility with gp2c*/ else if (is_func_named(x,"global")) { long i; for (i=1;i<=nb;i++) { long a=arg[i]; long en; if (tree[a].f==Faffect) { 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(x,"O") || (compatible==OLDALL && is_func_named(x,"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') { 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 { if (vn) op_push(OCnewptrlex, vn,n); else op_push(OCnewptrdyn, (long)ep,n); compilelvalue(a); op_push(OCpushptr, 0,n); } nbpointers++; break; } case 'I': case 'E': { struct codepos pos; long a=arg[j++]; int type=c=='I'?Gvoid:Ggen; long flag=c=='I'?0:FLreturn; getcodepos(&pos); if (lev) { long i; GEN vep=cgetg(lev+1,t_VECSMALL); GEN varg=cgetg(lev+1,t_VECSMALL); for(i=0;inbopcodes+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(talker,"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(talker,"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(talker, "Unknown prototype code `D...,%c,' for `%s'",c,ep->name); } break; case PPstar: switch(c) { case 's': return NULL; default: pari_err(talker,"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)); } 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(talker,"no function named \"%s\"",s); ep = do_alias(ep); if ((!EpSTATIC(ep) && EpVALENCE(ep)!=EpINSTALL) || !ep->value) pari_err(talker,"not a built-in/install'ed function: \"%s\"",s); C = genclosure(ep,ep->name,n,0); if (!C) pari_err(talker,"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 compilenode(long n, int mode, long flag) { long x,y; if (n<0) pari_err(bugparier,"compilenode"); x=tree[n].x; y=tree[n].y; switch(tree[n].f) { case Fseq: if (tree[x].f!=Fnoarg) compilenode(x,Gvoid,0); compilenode(y,mode,flag&FLreturn); return; case Ffacteurmat: compilefacteurmat(n,mode); if (mode==Ggen && !(flag&FLnocopy)) op_push(OCcopy,0,n); return; case Faffect: x = detag(x); if (tree[x].f==Fentry) { entree *ep=getvar(x); long vn=getmvar(ep); compilenode(y,Ggen,FLnocopy); if (vn) op_push(OCstorelex,vn,n); else op_push(OCstoredyn,(long)ep,n); if (mode!=Gvoid) { if (vn) { op_push(OCpushlex,vn,n); copyifclone(n,mode,flag,FLnocopy|FLnocopylex); } else { op_push(OCpushdyn,(long)ep,n); copyifclone(n,mode,flag,FLnocopy); } compilecast(n,Ggen,mode); } } else compilefunc(is_entry("_=_"),n,mode,0); 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(bugparier,"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; 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; 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==Faffect?tree[a].x:a); var_push(NULL,Lmy); } checkdups(arg,vep); op_push(OCgetargs,nb,y); frame_push(vep); for (i=1;i<=nb;i++) { long a=arg[i]; if (tree[a].f==Faffect) { struct codepos lpos; getcodepos(&lpos); compilenode(tree[a].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]; } } dbgstart=tree[y].str; if (y>=0 && tree[y].f!=Fnoarg) compilenode(y,Ggen,FLreturn); else compilecast(n,Gvoid,Ggen); op_push(OCpushgen, data_push(getfunction(&pos,nb,nbmvar,text)),n); if (nbmvar) op_push(OCsaveframe,!!(flag&FLreturn),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(bugparier,"compilenode"); } } GEN gp_closure(long n) { struct codepos pos; getcodepos(&pos); dbgstart=tree[n].str; compilenode(n,Ggen,FLreturn); return getfunction(&pos,0,0,strntoGENstr(tree[n].str,tree[n].len)); } 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)); } 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': 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!=Faffect) 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(talker,"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 '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(talker,"Unknown prototype code `%c*' for `%.*s'",c, tree[x].len, tree[x].str); } break; default: pari_err(bugparier,"PPproto %d in compilefunc",mod); } } } 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; } void optimizenode(long n) { long x,y; if (n<0) pari_err(bugparier,"optimizenode"); x=tree[n].x; y=tree[n].y; switch(tree[n].f) { case Fseq: if (tree[x].f!=Fnoarg) optimizenode(x); optimizenode(y); tree[n].flags=tree[x].flags&tree[y].flags; return; case Ffacteurmat: optimizefacteurmat(n); break; case Faffect: 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(bugparier,"optimizenode"); } } pari-2.5.5/src/language/opcode.h0000644000175000017500000000277212147140047015110 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} op_code; ENDEXTERN pari-2.5.5/src/language/eval.c0000644000175000017500000012077312162150422014556 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/allocatemem handling */ /* */ /********************************************************************/ static THREAD long br_status, br_count; enum { br_NONE = 0, br_BREAK, br_NEXT, br_MULTINEXT, br_RETURN }; 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)? gclone(x): NULL; if (y) gunclone(y); br_status = br_RETURN; return NULL; } GEN next0(long n) { if (n < 1) pari_err(talker,"positive integer expected in next"); 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(talker,"positive integer expected in break"); 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 (foreignFuncFree && ep->code && (*ep->code == 'x')) (*foreignFuncFree)(ep); /* function created by foreign interpreter */ 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(void) { pari_err(talker, "variable name expected"); } INLINE void checkvalue(entree *ep) { if (ep->valence==EpNEW) { pari_var_create(ep); ep->valence = EpVAR; ep->value = initial_value(ep); } else if (ep->valence!=EpVAR) err_var(); } /* 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 max) { if (c < 1 || c >= max) { if (max <= 2) pari_err(talker,"array index (%ld) out of allowed range [%s]",c,max==1?"none":"1"); else pari_err(talker,"array index (%ld) out of allowed range [1-%ld]",c,max-1); } } typedef struct matcomp { GEN *ptcell; GEN parent; int full_col, full_row; } matcomp; typedef struct gp_pointer { matcomp c; GEN x; 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(talker,"not a suitable VECSMALL component"); *pt = (GEN)itos(res); return; } t = typ(res); if (c->full_row) { if (t != t_VEC || lg(res) != lg(p)) pari_err(talker,"incorrect type or length in matrix 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 || lg(res) != lg(*pt)) pari_err(talker,"incorrect type or length in matrix 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; 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 void trace_push(long *pc, GEN C) { long tr; BLOCK_SIGINT_START tr = stack_new(&s_trace); trace[tr].pc = pc; trace[tr].closure = C; BLOCK_SIGINT_END } void push_lex(GEN a, GEN C) { long vn=stack_new(&s_var); struct var_lex *v=var+vn; v->flag = PUSH_VAL; v->value = a; if (C) trace_push(NULL, 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--; } void pari_init_evaluator(void) { sp=0; stack_init(&s_st,sizeof(*st),(void**)&st); stack_alloc(&s_st,32); s_st.n=s_st.alloc; rp=0; stack_init(&s_ptrs,sizeof(*ptrs),(void**)&ptrs); stack_alloc(&s_ptrs,16); s_ptrs.n=s_ptrs.alloc; stack_init(&s_var,sizeof(*var),(void**)&var); stack_init(&s_lvars,sizeof(*lvars),(void**)&lvars); stack_init(&s_trace,sizeof(*trace),(void**)&trace); br_res = NULL; } void pari_close_evaluator(void) { stack_delete(&s_st); stack_delete(&s_ptrs); stack_delete(&s_var); stack_delete(&s_lvars); stack_delete(&s_trace); } static gp_pointer * new_ptr(void) { if (rp==s_ptrs.n-1) { long i; gp_pointer *old = ptrs; (void)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 (!gcmpX(x)) err_var(); 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(bugparier,"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(); default: pari_err(bugparier,"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) return NULL; pc = *trace[fun].pc; C = trace[fun].closure; code = GSTR(gel(C,2))-1; oper = gel(C,3); 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; } void closure_err(void) { GEN base; const long lastfun = s_trace.n - 1; 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 = gel(trace[i].closure,6); /* 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=gel(C,6); if ((i==lastfun || lg(trace[i+1].closure)>=7)) { /* After a SIGINT, pc can be slightly off: ensure 0 <= pc < lg() */ long pc = minss(lg(mael(C,5,1))-1, trace[i].pc ? *trace[i].pc: 1); long offset = pc? mael3(C,5,1,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) { const long lastfun = s_trace.n - 1; long i, fun = lastfun; if (fun<0) return lastfun; while (fun>start && lg(trace[fun].closure)==6) fun--; for (i=fun; i<=lastfun; i++) { long *pc=trace[i].pc; push_frame(trace[i].closure, pc?*pc:-1); } return lastfun; } INLINE void st_alloc(long n) { if (sp+n>s_st.n) { stack_alloc(&s_st,n+16); s_st.n=s_st.alloc; if (DEBUGMEM>=2) pari_warn(warner,"doubling evaluator stack"); } } static void closure_eval(GEN C) { const char *code=GSTR(gel(C,2))-1; GEN oper=gel(C,3); GEN data=gel(C,4); long loper=lg(oper); long saved_sp=sp-C[1]; long saved_rp=rp; long j, nbmvar=0, nblvar=0; long pc = 0; /* pc need to be defined after a ^C */ if (isclone(C)) ++bl_refc(C); trace_push(&pc, C); if (lg(C)==8) { GEN z=gel(C,7); long l=lg(z)-1; 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->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->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->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->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); } break; case OCstoredyn: { entree *ep = (entree *)operand; checkvalue(ep); changevalue(ep, gel(st,--sp)); break; } case OCstorelex: changelex(operand,gel(st,--sp)); 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); if (typ(z)!=t_STR) z = GENtoGENstr(z); st[sp+operand] = (long) GSTR(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, av2; GEN x; sp--; av = st[sp-1]; x = gel(st,sp); av2 = (pari_sp)(x + lg(x)); if (av - av2 > 1000000) { if (DEBUGMEM>=2) pari_warn(warnmem,"eval: recovering %ld bytes", av - av2); x = gerepileupto(av, x); } 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(talker,"_[_]: not a vector"); 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; g->x = *(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; g->x = *(C->ptcell); break; default: pari_err(talker,"_[_]: not a vector"); } 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(talker,"_[_,_]: not a matrix"); check_array_index(d, lg(p)); check_array_index(c, lg(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(talker,"_[_,_]: not a matrix"); check_array_index(d, lg(p)); check_array_index(c, lg(p[d])); C->ptcell = (GEN *) gel(p,d)+c; C->parent = p; g->x = *(C->ptcell); break; } case OCcompoC: { GEN p=gel(st,sp-2); long c=st[sp-1]; if (typ(p)!=t_MAT) pari_err(talker,"_[,_]: not a matrix"); 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(talker,"_[,_]: not a matrix"); check_array_index(c, lg(p)); C->ptcell = (GEN *) p+c; C->full_col = c; C->parent = p; g->x = *(C->ptcell); break; } case OCcompoL: { GEN p=gel(st,sp-2); long r=st[sp-1]; sp--; if (typ(p)!=t_MAT) pari_err(talker,"_[_,]: not a matrix"); if (lg(p)==1) pari_err(talker,"a 0x0 matrix has no elements"); check_array_index(r,lg(p[1])); 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(talker,"_[_,]: not a matrix"); if (lg(p)==1) pari_err(talker,"a 0x0 matrix has no elements"); check_array_index(r,lg(p[1])); 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 = closure_evalnobrk(gel(st,sp-1)); pushlex(operand,z); } sp--; break; case OClocalvar: { long n = stack_new(&s_lvars); entree *ep = (entree *)operand; checkvalue(ep); lvars[n] = ep; nblvar++; pushvalue(ep,gel(st,--sp)); break; } case OClocalvar0: { long n = 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(notfuncer, fun); arity=fun[1]; if (n!=arity) { if (n>arity) pari_err(talker,"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(talker, "deep recursion"); #endif z = closure_return(fun); if (br_status) goto endeval; gel(st, sp-1) = z; break; } case OCnewframe: stack_alloc(&s_var,operand); s_var.n+=operand; nbmvar+=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(talker,"missing mandatory argument"); break; case OCcheckargs0: for (j=sp-1;operand;operand>>=1UL,j--) if ((operand&1L) && gel(st,j)) pari_err(talker,"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;javma = 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); } void evalstate_restore(struct pari_evalstate *state) { avma = state->avma; 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); } void evalstate_reset(void) { sp = 0; rp = 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); CATCH(numerr) { x = (GEN)1L; } TRY { x = closure_evalgen(C); } 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(talker, "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; gel(st,sp++)=x; for(i=2; i<=C[1]; i++) gel(st,sp++) = NULL; closure_evalvoid(C); } GEN closure_callgen1(GEN C, GEN x) { long i; gel(st,sp++)=x; for(i=2; i<=C[1]; i++) gel(st,sp++) = NULL; return closure_returnupto(C); } GEN closure_callgen2(GEN C, GEN x, GEN y) { long i; st_alloc(C[1]); gel(st,sp++)=x; gel(st,sp++)=y; for(i=3; i<=C[1]; i++) gel(st,sp++) = NULL; return closure_returnupto(C); } GEN closure_callgenvec(GEN C, GEN args) { long i, l = lg(args); st_alloc(C[1]); for (i = 1; i < l; i++) gel(st,sp++) = gel(args,i); for( ; i<=C[1]; i++) gel(st,sp++) = NULL; return closure_returnupto(C); } GEN closure_callgenall(GEN C, long n, ...) { va_list ap; long i; va_start(ap,n); st_alloc(C[1]); for (i = 1; i <=n; i++) gel(st,sp++) = va_arg(ap, GEN); for( ; i<=C[1]; 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); } 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) { char * code; GEN oper; long i; if (typ(C)!=t_CLOSURE) pari_err(typeer,"disassemble"); code=GSTR(gel(C,2))-1; oper=gel(C,3); 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 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 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 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; } } } pari-2.5.5/src/language/pariinl.c0000644000175000017500000000122212141040641015246 0ustar billbill/* $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. */ #define PARI_NO_MPINL_H #define INLINE #define DISABLE_INLINE #include "pari.h" pari-2.5.5/src/language/intnum.c0000644000175000017500000015002612147140047015140 0ustar billbill/* $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. */ #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, bit_accuracy(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, bit_accuracy(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)bit_accuracy_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 = bit_accuracy(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(talker,"incorrect table length in intnum initialization"); 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; } /* divide by 2 in place */ static GEN divr2_ip(GEN x) { setexpo(x, expo(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+1); gel(D.tabwp,k) = cgetr(prec+1); av = avma; ct = divr2_ip(addrr(et, invr(et))); st = subrr(et, ct); ext = invr( addrs(mpexp(mulur(3, st)), 1) ); setexpo(ext, expo(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+1); gel(D.tabwp,k) = cgetr(prec+1); 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+1); gel(D.tabwp,k) = cgetr(prec+1); 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(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+1); gel(D.tabwp,k) = cgetr(prec+1); gel(D.tabxm,k) = cgetr(prec+1); gel(D.tabwm,k) = cgetr(prec+1); 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+1); gel(D.tabwp,k) = cgetr(prec+1); gel(D.tabxm,k) = cgetr(prec+1); gel(D.tabwm,k) = cgetr(prec+1); 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); setexpo(extm1, expo(extm1) + D.m); setexpo(extp1, expo(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(typeer,"sumnum"); sig2 = gel(sig,2); sig = gel(sig,1); } else sig2 = gen_0; if (!isinR(sig) || !isinR(sig2)) pari_err(talker, "incorrect abscissa in sumnum"); if (gsigne(sig2) > 0) sig2 = mulcxmI(sig2); 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 = bit_accuracy(prec); t = gmul(pi, TABx0(tab)); if (sgn < 0) TABw0(tab) = gdiv(TABw0(tab), gch(t, prec)); else TABw0(tab) = gmul(TABw0(tab), gth(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), gch(t, prec)) : mulrr(gel(tabwp,k), gth(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), gch(t, prec)) : mulrr(gel(tabwm,k), gth(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(typeer,"intnum"); if (!isinC(a) || !isinC(b)) pari_err(typeer,"intnum"); 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(typeer,"intnum"); 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(typeer,"intnum"); 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(typeer,"intnum"); 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 */ }; #define is_fin_f(c) ((c) == f_REG || (c) == f_SING) /* is c finite */ #define is_slow_f(c) ((c) == f_YSLOW || (c) == f_YVSLO) /* slow case */ #define is_osc_f(c) ((c) == f_YOSCS || (c) == f_YOSCC) /* oscillating case */ 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 long code_aux(GEN a2, int warn) { GEN a2R = real_i(a2), a2I = imag_i(a2); long s = gsigne(a2I); if (s) { if(warn && !gequal0(a2R)) pari_warn(warner,"both nonzero real and imag. part in coding, real ignored"); return s > 0 ? f_YOSCC : f_YOSCS; } if (gequal0(a2R) || gcmpgs(a2R, -2)<=0) return f_YSLOW; if (gsigne(a2R) > 0) return f_YFAST; if (gcmpgs(a2R, -1) >= 0) pari_err(talker,"incorrect a or b in intnum"); return f_YVSLO; } static long transcode(GEN a, long warn) { GEN a1, a2; long la; if (typ(a) != t_VEC) return f_REG; la = lg(a); if (la == 1 || la > 3) pari_err(talker,"incorrect a or b in intnum"); if (la == 2) return gsigne(gel(a,1)) > 0 ? f_YSLOW : -f_YSLOW; a1 = gel(a,1); a2 = gel(a,2); if (typ(a1) != t_VEC) { if (!isinC(a1) || !isinR(a2) || gcmpgs(a2, -1) <= 0) pari_err(talker,"incorrect a or b in intnum"); return gsigne(a2) < 0 ? f_SING : f_REG; } if (lg(a1) != 2 || !isinC(a2)) pari_err(talker,"incorrect a or b in intnum"); return gsigne(gel(a1,1)) * code_aux(a2, warn); } /* 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(talker,"m too large in intnuminit"); l = prec + 1; codea = transcode(a, 1); codeb = transcode(b, 1); 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(typeer,"intnuminit0"); 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(typeer,"sumnuminit0"); return tab; } else m = itos(tab); return sumnuminit(a, m, sgn, prec); } /* here always eps = 2^(-k). */ static GEN myderiv_num(void *E, GEN (*eval)(void*, GEN), GEN a, GEN eps, long k, long prec) { GEN tmp = gmul2n(gsub(eval(E, gadd(a,eps)), eval(E, gsub(a,eps))), k - 1); return gprec_w(tmp, prec); } /* User-defined change of variable phi(t) = f(t), where t always goes from * -\infty to +\infty, and a and b are as in intnuminit. If [a,b] compact, * assume phi(t) odd, otherwise assume nothing. */ static int condfin(long code, GEN xw, GEN xwmod, long eps, long m, long k) { GEN x, w; eps -= 8; /* for safety. Lose 8 bits, but took 1 whole word extra. */ if (!is_osc_f(labs(code))) xw = xwmod; 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 + expi(stoi(10 * k)) < - eps; default: return 0; } } /* Do not change the numbers below unless you understand what you are doing. */ enum { f_COMP = -1, /* [a,b] */ f_SEMI = 0, /* [a,+-\infty[, no oscillation */ f_OSC1 = 1, /* [a,+-\infty[, oscillation */ f_INF = 2, /* ]-\infty,+\infty[, no oscillation */ f_OSC2 = 3 /* ]-\infty,+\infty[, oscillation */ }; #define not_osc(fl) ((fl) == f_COMP || (fl) == f_SEMI || (fl) == f_INF) #define not_odd(fl) ((fl) == f_SEMI || (fl) == f_OSC1) static GEN ffprime(void *E, GEN (*eval)(void*, GEN), GEN xpr, GEN xprn, GEN eps, long h, long precl) { GEN z = cgetg(3, t_VEC); gel(z,1) = eval(E, xpr); gel(z,2) = myderiv_num(E, eval, xprn, eps, h, precl); return z; } static GEN ffmodify(GEN tmp, GEN ab, long flag) { GEN z, t; if (not_osc(flag)) return tmp; t = ginv(gsubsg(1, gel(tmp,1))); z = cgetg(3, t_VEC); gel(z,1) = gmul(ab, t); gel(z,2) = gadd(t, gmul(gsqr(t), gmul(ab, gel(tmp,2)))); return z; } GEN intnuminitgen(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long m, long flext, long prec) { pari_sp ltop = avma; GEN hpr, hnpr, eps, pisurh = gen_0, tmpxw, tmpxwmodp, tmpxwmodm = gen_0, ab; long k, h, newprec, nt, lim, ntn, precl = prec + 1; long flag = f_SEMI, codea = transcode(a, 1), codeb = transcode(b, 1); intdata D; intinit_start(&D, m, flext, precl); if (flag < 0 || flag >= 3) pari_err(flagerr,"intnuminitgen"); lim = lg(D.tabxp) - 1; if (is_osc_f(labs(codea)) || is_osc_f(labs(codeb))) { pisurh = Pi2n(D.m, precl); 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) pari_err(talker,"infinities of the same sign in intnuminitgen"); if (labs(codea) != labs(codeb)) pari_err(talker,"infinities of different type in intnuminitgen"); flag = (flag == f_SEMI) ? f_INF : f_OSC2; } newprec = (3*precl - 1)>>1; h = bit_accuracy(precl)/2; eps = real2n(-h, newprec); if (not_osc(flag) || !gequal1(eval(E, gen_0))) { ab = real_0(precl); tmpxw = ffprime(E, eval, ab, real_0(newprec), eps, h, precl); tmpxwmodp = ffmodify(tmpxw, ab, flag); D.tabx0 = gel(tmpxwmodp,1); D.tabw0 = gel(tmpxwmodp,2); } else { tmpxw = gdiv(pol_x(0), gsubsg(1, eval(E, gadd(pol_x(0), zeroser(0, 4))))); D.tabx0 = gprec_w(polcoeff0(tmpxw, 0, 0), precl); D.tabw0 = gprec_w(polcoeff0(tmpxw, 1, 0), precl); } hpr = real2n(-D.m, precl); hnpr= real2n(-D.m, newprec); for (k = 1; k <= lim; k++) { int finb; ab = mulur(k, hpr); tmpxw = ffprime(E, eval, ab, mulur(k, hnpr), eps, h, precl); tmpxwmodp = ffmodify(tmpxw, ab, flag); D.tabxp[k] = tmpxwmodp[1]; D.tabwp[k] = tmpxwmodp[2]; finb = condfin(codeb, tmpxw, tmpxwmodp, D.eps, D.m, k); if (not_odd(flag)) { ab = negr(ab); tmpxw = ffprime(E, eval, ab, mulsr(-k, hnpr), eps, h, precl); tmpxwmodm = ffmodify(tmpxw, ab, flag); D.tabxm[k] = tmpxwmodm[1]; D.tabwm[k] = tmpxwmodm[2]; if (finb && condfin(codea, tmpxw, tmpxwmodm, D.eps, D.m, k)) break; } else if (finb) break; } nt = k - 1; if (!not_osc(flag)) { D.tabx0 = gmul(D.tabx0, pisurh); D.tabw0 = gmul(D.tabw0, pisurh); setlg(D.tabxp, nt + 1); D.tabxp = gmul(D.tabxp, pisurh); setlg(D.tabwp, nt + 1); D.tabwp = gmul(D.tabwp, pisurh); } if (flag == f_OSC1) { setlg(D.tabxm, nt + 1); D.tabxm = gmul(D.tabxm, pisurh); setlg(D.tabwm, nt + 1); D.tabwm = gmul(D.tabwm, pisurh); } ntn = not_odd(flag) ? nt : 0; return gerepilecopy(ltop, intinit_end(&D, nt, ntn)); } /* 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, 0), codeb = transcode(b, 0); 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(bugparier, "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 + 1; GEN S; tab = intnuminit0(a, b, tab, prec); /* prec + 1 is done in intnuminit0 */ 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); 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)); } static GEN auxinvcos(void *E, GEN t) { auxint_t *D = (auxint_t*) E; GEN tmp = gcos(gmul(D->R, t), D->prec); return gmul(tmp, D->f(D->E, gadd(D->a, mulcxI(t)))); } static GEN auxinvsin(void *E, GEN t) { auxint_t *D = (auxint_t*) E; GEN tmp = gsin(gmul(D->R, t), D->prec); return gmul(tmp, D->f(D->E, gadd(D->a, mulcxI(t)))); } static GEN auxinvexp(void *E, GEN t) { auxint_t *D = (auxint_t*) E; GEN tmp = gexp(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 flag, long prec) { auxint_t D; GEN z, zR, zI, tmpP, tmpN; if (typ(sig) != t_VEC) sig = mkvec2(sig, stoi(flag)); if (lg(sig) != 3 || !isinR(gel(sig,1)) || !isinR(gel(sig,2))) pari_err(typeer,"integral transform"); if (gsigne(gel(sig,2)) < 0) pari_err(talker,"exponential increase in integral transform"); 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); zR = intnum_i(&D, &auxinvcos, tmpN, tmpP, tab, prec); gel(tmpP,2) = gneg(gel(tmpP,2)); zI = intnum_i(&D, &auxinvsin, gettmpN(tmpP), tmpP, tab, prec); z = gadd(zR, mulcxI(zI)); } else { D.R = mulcxI(x); tmpP = gettmpP(gel(sig,2)); z = intnum(&D, &auxinvexp, 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) { return intinvintern(E, eval, sig, gneg(glog(x, prec)), tab, 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, 0]. */ GEN intlaplaceinv(void *E, GEN (*eval)(void*, GEN), GEN sig, GEN x, GEN tab, long prec) { return intinvintern(E, eval, sig, x, tab, 0, 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(typeer,"intmellininvshort"); if (gsigne(gel(sig,2)) <= 0) pari_err(talker,"need exponential decrease in intinvmellinshort"); 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) { GEN b, xa; long s, codea = transcode(a, 1); 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(talker,"x = 0 in Fourier"); 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; } static GEN auxfoursin(void *E, GEN t) { auxint_t *D = (auxint_t*) E; return gmul(gsin(gmul(t, D->a), D->prec), D->f(D->E, t)); } static GEN auxfourcos(void *E, GEN t) { auxint_t *D = (auxint_t*) E; return gmul(gcos(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 z, 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; z = intnum(&D, &auxfoursin, mytra(a, tmp, 0), mytra(b, tmp, 0), tab, prec); return z; } GEN intfouriercos(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN x, GEN tab, long prec) { auxint_t D; GEN z, 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; z = intnum(&D, &auxfourcos, mytra(a, tmp, 1), mytra(b, tmp, 1), tab, prec); return z; } 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(flagerr); return NULL; /* not reached */ } if (!z) pari_err(talker, "too many iterations in intnumromb"); 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(talker, "incorrect beginning value in sumnum"); 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.5.5/src/language/es.c0000644000175000017500000033311012147140047014232 0ustar billbill/* $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. */ /*******************************************************************/ /** **/ /** INPUT/OUTPUT SUBROUTINES **/ /** **/ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #include "anal.h" #ifdef _WIN32 #include #include "../systems/mingw/mingw.h" #endif 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 */ } 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(talker,"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 (t-2 >= F->t && t[-2] == '?') break; /* '?\' */ t--; if (!F->more_input) F->more_input = 1; goto END; } if (*s == '\r') s++; /* DOS */ if (*s == '\n') { if (t-2 >= F->t && t[-2] == '?') 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(talker,"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 input char */ if (c == '=') 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) { int first = 1; ulong used0, used; used0 = used = *s0 - b->buf; for(;;) { ulong left = b->len - used, l; char *s; if (left < 512) { fix_buffer(b, b->len << 1); left = b->len - used; *s0 = b->buf + used0; } s = b->buf + used; if (! IM->fgets(s, left, IM->file)) return first? NULL: *s0; /* EOF */ l = strlen(s); first = 0; if (l+1 < left || 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 *t; if (!f) return; if (logstyle == logstyle_color) { (void)fputs(s, f); return; } for (t = s; *t; t++) { if (*t != esc) { (void)fputc(*t, f); continue; } /* skip ANSI color escape sequence */ while (*++t != 'm') if (!*t) return; } } 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 initout(int initerr) { pari_infile = stdin; pari_outfile = stdout; pari_errfile = stderr; pariOut = &defaultOut; if (initerr) pariErr = &defaultErr; } 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(); } /* e binary exponent, return exponent in base ten */ static long ex10(long e) { return (long) ((e >= 0)? e*LOG10_2: -(-e*LOG10_2)-1); } 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 = stackmalloc(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 = stackmalloc(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 = lg(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)); z[1] = evalsigne(1) | evalexpo(expo(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 = stackmalloc( 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 = stackmalloc( 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 = lg(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(bit_accuracy(lx) - ex); if (beta) { /* z = |x| 10^beta, 10^b = 5^b * 2^b, 2^b goes into exponent */ if (beta > 0) { if (beta > 4e9) lx++; z = mulrr(x, rpowuu(5UL, (ulong)beta, lx+1)); } else { if (beta < -4e9) lx++; z = divrr(x, rpowuu(5UL, (ulong)-beta, lx+1)); } z[1] = evalsigne(1) | evalexpo(expo(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 */ buf0 = buf = stackmalloc( ls + 1+2+MAX_EXPO_LEN+1 ); point = ls - beta; /* position of . in s; < 0 or > 0 */ if (beta <= 0 || format == 'e' || (format == 'g' && point-1 < -4)) { /* e format */ wr_dec(buf, s, 1); buf += ls + 1; if (sp) *buf++ = ' '; *buf++ = exp_char; sprintf(buf, "%ld", point-1); } else { /* f format */ if (point > 0) /* write integer_part.fractional_part */ wr_dec(buf, s, point); /* point < ls since beta > 0 */ else { /* point <= 0, write fractional part */ *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 */ static void str_putc(outString *S, char c) { *S->cur++ = c; if (S->cur == S->end) { size_t l = S->size << 1; S->string = (char*)pari_realloc((void*)S->string, l); S->cur = S->string + S->size; S->end = S->string + l; S->size = l; } } static void str_init(outString *S) { S->size = 1024; S->string = S->cur = (char*)pari_malloc(S->size); 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; 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 = lg(gvalue[1]); for (i=1; i 0) caps = 0; else { caps = 1; base = -base; } buf0 = buf = stackmalloc(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(talker, "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; 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 = lg(gvalue[1]); 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); 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(talker, "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(talker, "two '.' in conversion specification"); pointflag = 1; goto nextch; /*------------------------------------------------------------------------ -- length modifiers ------------------------------------------------------------------------*/ case 'l': if (GENflag) pari_err(talker, "P/l length modifiers in the same conversion"); if (longflag) pari_err(impl, "ll length modifier in printf"); longflag = 1; goto nextch; case 'P': if (longflag) pari_err(talker, "P/l length modifiers in the same conversion"); if (GENflag) pari_err(talker, "'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(talker, "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 = stackmalloc(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 # include # 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 int col_index; /* output string wrapped after MAX_WIDTH characters (for gp -test) */ static void putc80(char c) { const int MAX_WIDTH = 76; if (c == '\n') col_index = 0; else if (col_index == MAX_WIDTH) { normalOutC('\n'); col_index = 1; } else col_index++; normalOutC(c); } static void puts80(const char *s) { while (*s) putc80(*s++); } static PariOUT pariOut80= {putc80, puts80, normalOutF}; void init80col(void) { col_index = 0; pariOut = &pariOut80; } /* 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 = stackmalloc(n); memcpy(t,s,n); return t; } 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; } /* returns a malloc-ed string, which should be freed after usage */ /* Returns pari_malloc()ed string */ static char * GENtostr_fun(GEN x, pariout_t *T, OUT_FUN out) { pari_sp av = avma; outString S; str_init(&S); out(x, T, &S); *S.cur = 0; avma = av; return S.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 ltoc(long n) { if (n <= 0 || n > 255) pari_err(talker, "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; default: pari_err(talker,"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):", x[1]); 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(talker,"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(talker, "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(talker, "this object uses debugging variables"); s = ep->name; if (strlen(s) >= len) pari_err(talker, "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(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_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(mael(g,5,3))>=2) { GEN v = gel(g,7), d = gmael3(g,5,3,1); long i, l = lg(v); str_puts(S,"my("); for(i=1; i1) str_putc(S,','); str_puts(S,ep->name); str_putc(S,'='); if (tex) texi(gel(v,l-i),T,S); else bruti(gel(v,l-i),T,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 = 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); if (lgpol(g)) { /* hack: we want g[i] = coeff of degree i. */ l = i + lgpol(g); 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 = avma; char *ev; i = valp(g); l = precp(g)+i; g = gel(g,4); ev = GENtostr(p); for (; i=7) { if (typ(g[6])==t_STR) str_puts(S, GSTR(gel(g,6))); else { str_putc(S,'('); str_puts(S,GSTR(gmael(g,6,1))); str_puts(S,")->"); print_context(g, T, S, 0); str_puts(S,GSTR(gmael(g,6,2))); } } else { str_puts(S,"{\""); str_puts(S,GSTR(gel(g,2))); str_puts(S,"\","); wr_vecsmall(T,S,gel(g,3)); 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 = lg(g[1]); 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(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, l; OUT_FUN print; if (typ(g) != t_MAT) { bruti(g,T,S); return; } r=lg(g); if (r==1 || lg(g[1])==1) { str_puts(S, "[;]"); return; } l = lg(g[1]); str_putc(S, '\n'); print = (typ(g[1]) == t_VECSMALL)? prints: bruti; for (i=1; i=6) { if (typ(g[6])==t_STR) str_puts(S, GSTR(gel(g,6))); else { str_putc(S,'('); str_puts(S,GSTR(gmael(g,6,1))); str_puts(S,")\\mapsto "); print_context(g, T, S ,1); str_puts(S,GSTR(gmael(g,6,2))); } } else { str_puts(S,"\\{\""); str_puts(S,GSTR(gel(g,2))); 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(g[1]) == t_VECSMALL)? prints: texi; l = lg(g[1]); 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); 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 THREAD 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(talker, "could not open requested file %s", 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; } /* 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(talker,"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_files(void) { last_filename = NULL; last_tmp_file = NULL; homedir = 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 (homedir) pari_free(homedir); 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"); CATCH(CATCH_ALL) { CATCH_RELEASE(); return 0; } TRY { int i; fprintf(f,"\n\n"); fflush(f); for (i=1; i<1000; i++) fprintf(f," \n"); fprintf(f,"\n"); fflush(f); } ENDCATCH; return 1; } pariFILE * try_pipe(const char *cmd, int fl) { #ifndef HAVE_PIPES pari_err(archer); 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(archer); f = pari_unique_filename("pipe"); s = stackmalloc(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(talker,"[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 } /* 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 */ # include 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 #include 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); 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)); 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 = time(NULL); (void)strftime(buf,max,s,localtime(&t)); } #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; n++; } dirs = (char**) pari_malloc((n + 2)*sizeof(char *)); for (s=v, i=0; i<=n; i++) { char *end = s + strlen(s), *f = end; while (f > s && *--f == '/') *f = 0; 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 = stackmalloc(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 = stackmalloc(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; } /* 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 = stackmalloc(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(talker,"You never gave me anything to read!"); file = try_open(s); if (!file) pari_err(openfiler,"input",s); return pari_infile = pari_get_infile(s,file)->file; } /* return 1 if s starts by '/' or './' or '../' */ static int 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 (is_absolute(s)) { if ((f = try_name(s))) return f; } else { size_t lens = strlen(s); char **tmp = GP_DATA->path->dirs; for ( ; *tmp; tmp++) { /* make room for '/' and '\0', try_name frees it */ char *t = (char*)pari_malloc(2 + lens + strlen(*tmp)); sprintf(t,"%s/%s",*tmp,s); if ((f = try_name(t))) return f; } } pari_err(openfiler,"input",name); return NULL; /*not reached*/ } static int is_magic_ok(FILE *f); void switchout(const char *name) { if (name) { FILE* f; /* Only do the read-check for ordinary files * (to avoid blocking on pipes for example). */ if (pari_is_file(name)) { f = fopen(name, "r"); if (f) { if (is_magic_ok(f)) pari_err(talker,"%s is a GP binary file. Please use writebin", name); fclose(f); } } f = fopen(name, "a"); if (!f) pari_err(openfiler,"output",name); pari_outfile = f; } else if (pari_outfile != stdout) { fclose(pari_outfile); pari_outfile = stdout; } } /*******************************************************************/ /** **/ /** I/O IN BINARY FORM **/ /** **/ /*******************************************************************/ #define _fwrite(a,b,c,d) \ if (fwrite((a),(b),(c),(d)) < (c)) pari_err(talker,"write failed") #define _fread(a,b,c,d) \ if (fread((a),(b),(c),(d)) < (c)) pari_err(talker,"read failed") #define _lfread(a,b,c) _fread((a),sizeof(long),(b),(c)) #define _cfread(a,b,c) _fread((a),sizeof(char),(b),(c)) #define _lfwrite(a,b,c) _fwrite((a),sizeof(long),(b),(c)) #define _cfwrite(a,b,c) _fwrite((a),sizeof(char),(b),(c)) #define BIN_GEN 0 #define NAM_GEN 1 #define VAR_GEN 2 static long rd_long(FILE *f) { long L; _lfread(&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); _cfread(s, L, f); return s; } void writeGEN(GEN x, FILE *f) { fputc(BIN_GEN,f); wrGEN(x, f); } 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; _lfread(GENbinbase(p), L,f); return bin_copy(p); } GEN readobj(FILE *f, int *ptc) { int c = fgetc(f); GEN x = NULL; switch(c) { case BIN_GEN: x = rdGEN(f); break; case NAM_GEN: case VAR_GEN: { char *s = rdstr(f); if (!s) pari_err(talker,"malformed binary file (no name)"); if (c == NAM_GEN) { x = rdGEN(f); 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 EOF: break; default: pari_err(talker,"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 = stackmalloc(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"); int already = f? 1: 0; if (f) { int ok = check_magic(name,f); fclose(f); if (!ok) pari_err(openfiler,"binary output",name); } f = fopen(name,"a"); if (!f) pari_err(openfiler,"binary output",name); if (!already) write_magic(f); if (x) writeGEN(x,f); else { long v, maxv = pari_var_next(); for (v=0; vvalue,ep->name,f); } } 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; GEN x,y,z; int cx = 0 /* gcc -Wall */, cy; if (!check_magic(name,f)) return NULL; x = z = NULL; while ((y = readobj(f, &cy))) { if (x && cx == BIN_GEN) z = z? shallowconcat(z, mkvec(x)): mkvec(x); x = y; cx = cy; } if (z) { if (x && cx == BIN_GEN) z = z? shallowconcat(z, mkvec(x)): mkvec(x); if (DEBUGLEVEL) pari_warn(warner,"%ld unnamed objects read. Returning then in a vector", lg(z)-1); x = gerepilecopy(av, z); if (vector) *vector = 1; } else if (vector) *vector = 0; return x; } /*******************************************************************/ /** **/ /** GP I/O **/ /** **/ /*******************************************************************/ /* print a vector of GENs */ void out_print0(PariOUT *out, 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) out_puts(out, GSTR(x)); /* text surrounded by "" otherwise */ else { char *s = GENtostr_fun(x, GP_DATA->fmt, f); out_puts(out, s); free(s); } } } void print0(GEN g, long flag) { out_print0(pariOut, g, flag); } /* 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); free(s); pari_flush(); } /* GP only */ GEN Strprintf(const char *fmt, GEN args) { char *s = dopr_arg_vector(args, fmt); GEN z = strtoGENstr(s); 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); 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); } 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; } /* 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); 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) { pari_err(user, g); } void warning0(GEN g) { pari_warn(user, 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; } /* Store last_was_newline before writing to restore it after writing. */ static int wr_last_was_newline; /* Start writing to file s */ static void wr_init(const char *s) { char *t = wr_check(s); switchout(t); pari_free(t); wr_last_was_newline = pari_last_was_newline(); } /* End writing to file s, go back to stdout */ static void wr_finish(void) { pari_flush(); switchout(NULL); pari_set_last_newline(wr_last_was_newline); } #define WR_NL() pari_putc('\n'); wr_finish() #define WR_NO() wr_finish() void write0 (const char *s, GEN g) { wr_init(s); print0(g, f_RAW); WR_NL(); } void writetex(const char *s, GEN g) { wr_init(s); print0(g, f_TEX); WR_NL(); } void write1 (const char *s, GEN g) { wr_init(s); print0(g, f_RAW); WR_NO(); } 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 * p <= 0, called from %` (|p| backquotes, possibly 0) */ GEN gp_history(gp_hist *H, long p, char *old, char *entry) { ulong t = H->total, s = H->size; GEN z; if (!t) pari_err(old?syntaxer:talker,"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 = stackmalloc(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(syntaxer, str, old, entry); } z = H->res[ (p-1) % s ]; if (!z) { char *str = stackmalloc(128); sprintf(str, "History result %%%ld has been deleted (histsize changed)", p); pari_err(syntaxer, str, old, entry); } return z; } static GEN set_hist_entry(gp_hist *H, GEN x) { int i = H->total % H->size; H->total++; if (H->res[i]) gunclone(H->res[i]); return H->res[i] = gclone(x); } GEN pari_get_hist(long p) { return gp_history(GP_DATA->hist, p, NULL,NULL); } GEN pari_add_hist(GEN x) { return set_hist_entry(GP_DATA->hist, x); } ulong pari_nb_hist(void) { return GP_DATA->hist->total; } /*******************************************************************/ /** **/ /** TEMPORARY FILES **/ /** **/ /*******************************************************************/ #ifdef __WIN32 # include /* for getpid */ #endif #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 writeable", 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; #ifdef __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(talker,"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(talker,"couldn't find a suitable name for a tempdir (%s)",s); return buf; } pari-2.5.5/src/language/paricfg.c0000644000175000017500000000147312147140047015242 0ustar billbill/* $Id$ 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; pari-2.5.5/src/language/default.c0000644000175000017500000004731312147140047015256 0ustar billbill/* $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. */ #include "pari.h" #include "paripriv.h" /* Simple-minded parsing utilities. These are forbidden to use the GP stack * which may not exist at this point [e.g upon GP initialization] */ #ifdef MAXPATHLEN # define GET_SEP_SIZE MAXPATHLEN #else # define GET_SEP_SIZE 128 #endif /* Return all chars, up to next separator * [as strtok but must handle verbatim character string] */ char* get_sep(const char *t) { static char buf[GET_SEP_SIZE], *lim = buf + GET_SEP_SIZE; char *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 == lim) break; if (! (*s++ = *t++) ) return buf; } if (s == lim) pari_err(talker,"get_sep: argument too long (< %ld chars)", GET_SEP_SIZE); } } 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(syntaxer,"integer too large",s,s); n *= 10; m = n; n += *p++ - '0'; if (n < m) pari_err(syntaxer,"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(syntaxer,"integer too large",s,s); } if (*p) pari_err(syntaxer,"I was expecting an integer here", s, s); return n; } long get_int(const char *s, long dflt) { char *p = get_sep(s); long n; int minus = 0; if (*p == '-') { minus = 1; p++; } if (!isdigit((int)*p)) return dflt; n = (long)my_int(p); if (n < 0) pari_err(syntaxer,"integer too large",s,s); return minus? -n: n; } ulong get_uint(const char *s) { char *p = get_sep(s); if (*p == '-') pari_err(syntaxer,"arguments must be positive integers",s,s); return my_int(p); } /********************************************************************/ /* */ /* 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 = stackmalloc(64 + strlen(s)); (void)sprintf(t, "default: incorrect value for %s [0:off / 1:on]", s); pari_err(syntaxer, 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 = stackmalloc(strlen(s) + 2 * 20 + 40); (void)sprintf(buf, "default: incorrect value for %s [%lu-%lu]", s, Min, Max); pari_err(syntaxer, 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(fmt->sigd); 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(syntaxer,"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 <= 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(syntaxer,"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 = stackmalloc(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)); } static THREAD long dbg = -1; void dbg_block(void) { if (DEBUGLEVEL) { dbg = DEBUGLEVEL; DEBUGLEVEL = 0; } } void dbg_release(void) { if (dbg >= 0) { DEBUGLEVEL = dbg; dbg = -1; } } 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->res = (GEN *) pari_calloc(s * sizeof(GEN)); } GEN sd_histsize(const char *v, long flag) { gp_hist *H = GP_DATA->hist; ulong n = H->size; GEN r = sd_ulong(v,flag,"histsize",&n, 1, (LONG_MAX / sizeof(long)) - 1,NULL); if (n != H->size) { const ulong total = H->total; long g, h, k, kmin; GEN *resG = H->res, *resH; /* G = old data, H = new one */ size_t sG = H->size, sH; init_hist(GP_DATA, n, total); if (!total) return r; resH = H->res; sH = H->size; /* copy relevant history entries */ g = (total-1) % sG; h = k = (total-1) % sH; kmin = k - minss(sH, sG); for ( ; k > kmin; k--, g--, h--) { resH[h] = resG[g]; resG[g] = NULL; if (!g) g = sG; if (!h) h = sH; } /* clean up */ for ( ; resG[g]; g--) { gunclone(resG[g]); if (!g) g = sG; } pari_free((void*)resG); } 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(openfiler,"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 oldstyle = logstyle; GEN res = sd_ulong(v,flag,"log", &logstyle, 0, 3, msg); if (!oldstyle != !logstyle) /* Compare converts to boolean */ { /* toggled LOG */ if (oldstyle) { /* close log */ if (flag == d_ACKNOWLEDGE) pari_printf(" [logfile was \"%s\"]\n", current_logfile); fclose(pari_logfile); pari_logfile = NULL; } else pari_logfile = open_logfile(current_logfile); } if (pari_logfile && oldstyle != logstyle && logstyle == 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$"); } 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_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_primelimit(const char *v, long flag) { ulong max = maxprime(), n = max; GEN r = sd_ulong(v,flag,"primelimit",&n, 0,2*(ulong)(LONG_MAX-1024) + 1,NULL); if (n != max) { byteptr ptr = initprimes(n); pari_free(diffptr); diffptr = ptr; } return r; } 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_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 *) 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; } GEN sd_path(const char *v, long flag) { gp_path *p = GP_DATA->path; 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(" path = \"%s\"\n",p->PATH); return gnil; } 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(talker,"[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) 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; 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); stack_delete(&st); return gnil; } ep = is_entry_intern(s, defaults_hash, NULL); if (!ep) { pari_err(talker,"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 D->path */ static void init_path(gp_data *D) { gp_path *path = D->path; path->PATH = pari_strdup(pari_default_path()); 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; static pari_timer __T; D->flags = 0; /* GP-specific */ D->breakloop = 1; D->echo = 0; D->lim_lines = 0; D->recover = 1; D->chrono = 0; D->strictmatch = 1; D->simplify = 1; D->secure = 0; D->use_readline= 0; D->last_time = 0; D->T = &__T; D->hist = &__HIST; D->pp = &__PP; D->path = &__PATH; init_fmt(D); init_hist(D, 5000, 0); init_path(D); init_pp(D); return D; } pari-2.5.5/src/language/parse.y0000644000175000017500000001700612147140047014766 0ustar billbill%{ /* $Id$ 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" %} %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 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 '.' MAT %left "++" "--" %left '(' %left ':' %type seq sequnused matrix matrix_index expr %type lvalue %type matrixelts matrixlines arg listarg definition %type funcid memberid %type backticks history %destructor { pari_discarded++; } seq matrix matrix_index expr lvalue matrixelts matrixlines arg listarg definition funcid memberid backticks history %% sequnused: seq {$$=$1;} | seq error {$$=$1; pari_unused_chars=@1.end;YYABORT;} ; seq: /**/ %prec SEQ {$$=newnode(Fnoarg,-1,-1,&@$);} | expr %prec SEQ {$$=$1;} | seq ';' {$$=$1; @$=@1;} | seq ';' expr {$$=newnode(Fseq,$1,$3,&@$);} ; matrix_index: '[' expr ',' expr ']' {$$=newnode(Fmatrix,$2,$4,&@$);} | '[' expr ']' {$$=newnode(Fmatrix,$2,-1,&@$);} | '[' expr ',' ']' {$$=newnode(FmatrixL,$2,-1,&@$);} | '[' ',' expr ']' {$$=newnode(FmatrixR,$3,-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,&@$);} ; 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;} | definition {$$=$1;} | lvalue '=' expr {$$=newnode(Faffect,$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(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 %prec MAT {$$=newnode(Ffacteurmat,$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(Ffacteurmat,$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,&@$);} | '[' ';' ']' {$$=newnode(Fmat,-1,-1,&@$);} | '[' matrixelts ']' {$$=newnode(Fvec,$2,-1,&@$);} | '[' matrixlines ']' {$$=newnode(Fmat,$2,-1,&@$);} | '[' error ']' {$$=-1; YYABORT;} ; 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.5.5/src/language/hash.c0000644000175000017500000001337512147140047014556 0ustar billbill/* $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. */ #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(talker, "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*)) { hashtable *h = (hashtable*)pari_malloc(sizeof(hashtable)); int i = get_prime_index(minsize); ulong len = hashprimes[i]; h->table = (hashentry**)pari_calloc(len * sizeof(hashentry*)); 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 = (hashentry*) pari_malloc(sizeof(hashentry)); ulong index; if (++(h->nb) > h->maxnb && h->pindex < hashprimes_len-1) { /* double table size */ ulong i, newlen = hashprimes[++(h->pindex)]; hashentry *E, **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; } 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 = h->hash(k); hashentry *e = h->table[ hash % h->len ]; while (e) { if (hash == e->hash && h->eq(k, e->key)) return e; e = e->next; } return NULL; /* not found */ } 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; for (i = 0; i < h->len; i++) { hashentry *e = h->table[i]; while (e) { hashentry *f = e; e = e->next; free(f); } } free(h->table); 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); for ( ; e->key; e++) hash_link(h, e); 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 compound(ulong h, ulong a) { return (h << 1) ^ 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 = compound(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 = compound(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 = compound(h, x[1]); i = 2; } else i = 1; lx = lg(x); for (; i < lx; i++) h = compound(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.5.5/src/desc/0000755000175000017500000000000012212611624012606 5ustar billbillpari-2.5.5/src/desc/gen_proto0000755000175000017500000000337411636712103014542 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, 'symbolic_operators' => 13, 'member_functions' => 14, 'programming/internals' => 15, 'default' => 16, ); print <) { if (/^% *SECTION *: *(.*) */) { my ($sec) = $1; for ( sort grep { $funcs{$_}->{Section} eq $sec } keys %funcs ) { my ($fun) = $funcs{$_}; my ($doc) = $fun->{Doc}; next if (!defined($doc)); my ($args) = $fun->{Help}; my ($v); $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 = "\$($v)\$"; } if ($doc !~ /\\syn\w*{/ && $sec !~ /programming\/control/) { $doc .= library_syntax($fun, $args); } s/_def_//; my ($secname) = $_; my ($l) = $_; $l = "def,$l" if ($fun->{Section} =~ 'default'); if ($secname =~ s/_/\\_/g) { print "\n\\subsec{$secname}$v: \\kbdsidx{$l}\\label{se:$l}$doc\n"; } else { print "\n\\subsecidx{$secname}$v: \\label{se:$l}$doc\n"; } } } print; } sub library_syntax { my ($fun, $args) = @_; return '' if ($fun->{Class} =~ /^(highlevel|gp|default|gp_default)$/); my ($Cname) = $fun->{'C-Name'}; 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"; $args = ''; @vars=(); for ($i = 0; $i <= $#proto; ) { my ($c) = $proto[$i++]; if ($c eq 'l') { $type = "long"; next; } if ($c eq 'v') { $type = "void"; next; } if ($c =~ /^[GWIE]$/) {$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 ($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.5.5/src/desc/whatnow0000755000175000017500000000412411636712103014227 0ustar billbill#!/usr/bin/perl -w ################################################## # # Outputs the whatnow_list to be included in gp.c # ################################################## $src = ".."; $special = "\@"; %funold = read_oldfun("$src/language/compat.c"); %gpold = read_oldfun("$src/gp/gp_init.c"); for ( read_dico() ) { my ($oldname,$name,$arg,$oldarg) = split(/$special/); if ($funold{$oldname}) { push(@funres, get_new($name,$oldarg,$arg)); next; } if ($gpold{$oldname}) { push(@gpres, get_new($name,$oldarg,$arg)); next; } bug("5: $oldname\n"); } print "/* generated by the perl script 'whatnow' */\n" . "static const whatnow_t whatnowlist[]={\n" . join(",\n",@funres) . ",\n\n" . join(",\n",@gpres) . "\n};\n"; sub get_new { my($name, $oldarg,$arg) = @_; return "_SAME" if ($name eq "="); return "_REMOV" if ($name eq ""); return "{\"$name\",\"$oldarg\",\"$arg\"}"; } sub bug { die "BUG$_[0]\n"; } sub o_r { my($f) = $_[0]; open(IN,"<$f") || die "can't open $f\n"; } sub read_oldfun { o_r($_[0]); my(%fun); while() { 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.5.5/src/desc/merge_8220000755000175000017500000000041711636712103014233 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.5.5/src/desc/PARI/0000755000175000017500000000000012212611624013341 5ustar billbillpari-2.5.5/src/desc/PARI/822.pm0000755000175000017500000000715512141040641014221 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","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.5.5/src/funclist0000644000175000017500000011064512200714316013450 0ustar billbill3044099110 1085 ../functions/conversions/Col 4195552700 684 ../functions/conversions/List 981428093 924 ../functions/conversions/Mat 449317541 715 ../functions/conversions/Mod 1312883508 1771 ../functions/conversions/Pol 191610894 913 ../functions/conversions/Polrev 2844602529 620 ../functions/conversions/Qfb 4075984150 996 ../functions/conversions/Ser 654626246 818 ../functions/conversions/Set 4289873903 778 ../functions/conversions/Str 1983631051 398 ../functions/conversions/Strchr 3668703910 592 ../functions/conversions/Strexpand 1117955044 413 ../functions/conversions/Strprintf 2125909664 423 ../functions/conversions/Strtex 2702760381 1000 ../functions/conversions/Vec 3463392490 501 ../functions/conversions/Vecrev 3909008146 638 ../functions/conversions/Vecsmall 1275004057 370 ../functions/conversions/binary 130657493 883 ../functions/conversions/bitand 2352397645 600 ../functions/conversions/bitneg 1138344667 706 ../functions/conversions/bitnegimply 2059074700 616 ../functions/conversions/bitor 1737908276 803 ../functions/conversions/bittest 351827735 633 ../functions/conversions/bitxor 1456424929 513 ../functions/conversions/ceil 833479451 1129 ../functions/conversions/centerlift 394649425 1655 ../functions/conversions/component 2027282389 401 ../functions/conversions/conj 4003200502 838 ../functions/conversions/conjvec 2494482002 1105 ../functions/conversions/denominator 2072628265 514 ../functions/conversions/floor 689569802 220 ../functions/conversions/frac 293423956 246 ../functions/conversions/imag 1061890972 1035 ../functions/conversions/length 2385250408 1310 ../functions/conversions/lift 4165166886 433 ../functions/conversions/norm 391482101 810 ../functions/conversions/norml2 765810884 922 ../functions/conversions/numerator 412890821 334 ../functions/conversions/numtoperm 622159595 369 ../functions/conversions/padicprec 1553291691 283 ../functions/conversions/permtonum 3740885078 2792 ../functions/conversions/precision 1360548917 3016 ../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 2485744047 948 ../functions/conversions/valuation 4127892820 1084 ../functions/conversions/variable 2091712008 516 ../functions/default/TeXstyle 1101063589 291 ../functions/default/breakloop 3415930772 2194 ../functions/default/colors 4273902001 2220 ../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 4063419121 773 ../functions/default/factor_add_primes 3281972225 671 ../functions/default/factor_proven 3860891309 1410 ../functions/default/format 98138103 1016 ../functions/default/graphcolormap 3446126174 403 ../functions/default/graphcolors 3316457589 393 ../functions/default/help 1229391942 562 ../functions/default/histfile 3654358528 443 ../functions/default/histsize 220523559 556 ../functions/default/lines 2950182014 774 ../functions/default/log 4131263332 249 ../functions/default/logfile 1014775201 467 ../functions/default/new_galois_format 4079030132 1415 ../functions/default/output 140801756 712 ../functions/default/parisize 2366699578 712 ../functions/default/path 1991406625 395 ../functions/default/prettyprinter 2649834117 709 ../functions/default/primelimit 4187737678 1452 ../functions/default/prompt 366853813 349 ../functions/default/prompt_cont 3343395058 317 ../functions/default/psfile 3790396319 438 ../functions/default/readline 2736895137 749 ../functions/default/realprecision 312510814 312 ../functions/default/recover 1228873450 456 ../functions/default/secure 699347451 257 ../functions/default/seriesprecision 4068861417 868 ../functions/default/simplify 2150187344 472 ../functions/default/strictmatch 3418162328 458 ../functions/default/timer 4197571579 1431 ../functions/elliptic_curves/ellL1 1911747593 227 ../functions/elliptic_curves/elladd 4206561913 805 ../functions/elliptic_curves/ellak 1796095883 348 ../functions/elliptic_curves/ellan 1664571559 1126 ../functions/elliptic_curves/ellanalyticrank 532070338 1998 ../functions/elliptic_curves/ellap 1762262057 611 ../functions/elliptic_curves/ellbil 908601178 489 ../functions/elliptic_curves/ellchangecurve 488758109 537 ../functions/elliptic_curves/ellchangepoint 1622337703 620 ../functions/elliptic_curves/ellconvertname 760988858 239 ../functions/elliptic_curves/elldivpol 3098405402 1055 ../functions/elliptic_curves/elleisnum 1704229132 629 ../functions/elliptic_curves/elleta 2691471638 571 ../functions/elliptic_curves/ellgenerators 3951254276 948 ../functions/elliptic_curves/ellglobalred 1288295814 1097 ../functions/elliptic_curves/ellgroup 3638838722 1015 ../functions/elliptic_curves/ellheight 1516218458 797 ../functions/elliptic_curves/ellheightmatrix 2488118625 654 ../functions/elliptic_curves/ellidentify 1413415490 4043 ../functions/elliptic_curves/ellinit 240812548 602 ../functions/elliptic_curves/ellisoncurve 3064568940 281 ../functions/elliptic_curves/ellj 2569301185 1257 ../functions/elliptic_curves/elllocalred 260790555 1062 ../functions/elliptic_curves/elllog 622457936 758 ../functions/elliptic_curves/elllseries 904157268 782 ../functions/elliptic_curves/ellminimalmodel 3807969137 577 ../functions/elliptic_curves/ellmodulareqn 3347233273 1223 ../functions/elliptic_curves/ellorder 712202039 307 ../functions/elliptic_curves/ellordinate 2158590385 926 ../functions/elliptic_curves/ellpointtoz 1992661816 1066 ../functions/elliptic_curves/ellpow 727595452 678 ../functions/elliptic_curves/ellrootno 3929514340 1044 ../functions/elliptic_curves/ellsearch 1125418328 903 ../functions/elliptic_curves/ellsigma 2796370435 241 ../functions/elliptic_curves/ellsub 3599611331 1078 ../functions/elliptic_curves/elltaniyama 463127701 362 ../functions/elliptic_curves/elltatepairing 3346414551 1235 ../functions/elliptic_curves/elltors 2219345950 318 ../functions/elliptic_curves/ellweilpairing 3123014222 1216 ../functions/elliptic_curves/ellwp 3260078023 955 ../functions/elliptic_curves/ellzeta 2085796917 617 ../functions/elliptic_curves/ellztopoint 977116536 393 ../functions/gp2c/clone 4282475994 385 ../functions/gp2c/copy 3783251634 108 ../functions/gp2c/unclone 1891743718 82 ../functions/gp2c_internal/_avma 2835164719 834 ../functions/gp2c_internal/_badtype 3595759624 2823 ../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 4257810397 134 ../functions/gp2c_internal/_toGENstr 445566870 730 ../functions/gp2c_internal/_tovec 816392135 1833 ../functions/gp2c_internal/_typedef 2426792003 312 ../functions/gp2c_internal/_wrap 1890857364 592 ../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 3977814377 5251 ../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 1207030536 3086 ../functions/linear_algebra/algdep 452539389 2191 ../functions/linear_algebra/charpoly 1285253540 1992 ../functions/linear_algebra/concat 929929180 2452 ../functions/linear_algebra/lindep 1885213010 438 ../functions/linear_algebra/listcreate 3413287768 475 ../functions/linear_algebra/listinsert 371937160 368 ../functions/linear_algebra/listkill 3372792055 484 ../functions/linear_algebra/listpop 1191932916 818 ../functions/linear_algebra/listput 2273300176 415 ../functions/linear_algebra/listsort 448200866 1135 ../functions/linear_algebra/matadjoint 1203371924 193 ../functions/linear_algebra/matcompanion 1524320634 832 ../functions/linear_algebra/matdet 925390974 996 ../functions/linear_algebra/matdetint 3381968663 278 ../functions/linear_algebra/matdiagonal 1629228465 208 ../functions/linear_algebra/mateigen 859727976 709 ../functions/linear_algebra/matfrobenius 1006778180 243 ../functions/linear_algebra/mathess 1459166046 263 ../functions/linear_algebra/mathilbert 3597059644 2503 ../functions/linear_algebra/mathnf 3195530342 794 ../functions/linear_algebra/mathnfmod 2566860388 351 ../functions/linear_algebra/mathnfmodid 229723112 196 ../functions/linear_algebra/matid 1202630193 534 ../functions/linear_algebra/matimage 453168051 456 ../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 2506747564 601 ../functions/linear_algebra/matker 3907458254 868 ../functions/linear_algebra/matkerint 1800646688 424 ../functions/linear_algebra/matmuldiagonal 2929869545 432 ../functions/linear_algebra/matmultodiagonal 4147150140 452 ../functions/linear_algebra/matpascal 4135328056 138 ../functions/linear_algebra/matrank 2190495821 621 ../functions/linear_algebra/matrix 1651195523 1536 ../functions/linear_algebra/matrixqz 2001534037 349 ../functions/linear_algebra/matsize 217283128 1574 ../functions/linear_algebra/matsnf 2590588036 339 ../functions/linear_algebra/matsolve 997433783 1442 ../functions/linear_algebra/matsolvemod 253457056 431 ../functions/linear_algebra/matsupplement 4081660555 207 ../functions/linear_algebra/mattranspose 4127728161 309 ../functions/linear_algebra/minpoly 2663304455 1022 ../functions/linear_algebra/qfgaussred 830595753 480 ../functions/linear_algebra/qfjacobi 2738765226 3148 ../functions/linear_algebra/qflll 2571047474 1825 ../functions/linear_algebra/qflllgram 1395193301 5348 ../functions/linear_algebra/qfminim 884649199 631 ../functions/linear_algebra/qfperfection 2446690748 835 ../functions/linear_algebra/qfrep 182597421 360 ../functions/linear_algebra/qfsign 1444517969 491 ../functions/linear_algebra/setintersect 4187498261 521 ../functions/linear_algebra/setisset 739838440 537 ../functions/linear_algebra/setminus 2935734843 1487 ../functions/linear_algebra/setsearch 559172318 461 ../functions/linear_algebra/setunion 2343012690 397 ../functions/linear_algebra/trace 3862112591 2393 ../functions/linear_algebra/vecextract 505469117 4313 ../functions/linear_algebra/vecsort 3969360427 869 ../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 1352873984 139 ../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 2389381105 189 ../functions/member_functions/r1 2681820181 189 ../functions/member_functions/r2 3310137925 236 ../functions/member_functions/reg 2212261111 305 ../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 430818772 129 ../functions/member_functions/w 1665968088 171 ../functions/member_functions/zk 2924685257 142 ../functions/member_functions/zkst 2219184268 900 ../functions/number_fields/bnfcertify 654416520 1799 ../functions/number_fields/bnfcompress 2793286384 307 ../functions/number_fields/bnfdecodemodule 3645768719 5201 ../functions/number_fields/bnfinit 2768253267 629 ../functions/number_fields/bnfisintnorm 3893778090 1521 ../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 736235269 3011 ../functions/number_fields/bnrL1 3690166239 721 ../functions/number_fields/bnrclassno 3507816003 1184 ../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 161447682 1927 ../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 4269520571 1345 ../functions/number_fields/galoisexport 1065509842 1919 ../functions/number_fields/galoisfixedfield 40700614 1444 ../functions/number_fields/galoisgetpol 690345336 1105 ../functions/number_fields/galoisidentify 3503832005 3873 ../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 2581761397 1331 ../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 2598883859 1540 ../functions/number_fields/idealhnf 1199602370 777 ../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 864949477 1275 ../functions/number_fields/idealmul 2213617432 214 ../functions/number_fields/idealnorm 590254486 900 ../functions/number_fields/idealpow 1026089842 1712 ../functions/number_fields/idealprimedec 2568750931 1357 ../functions/number_fields/idealramgroups 477008975 2910 ../functions/number_fields/idealred 2034048002 2100 ../functions/number_fields/idealstar 3393592167 1123 ../functions/number_fields/idealtwoelt 1614130949 338 ../functions/number_fields/idealval 2450987406 330 ../functions/number_fields/matalgtobasis 4263225345 330 ../functions/number_fields/matbasistoalg 3075174824 1435 ../functions/number_fields/modreverse 923642746 645 ../functions/number_fields/newtonpoly 74387094 580 ../functions/number_fields/nfalgtobasis 1294534313 1950 ../functions/number_fields/nfbasis 794927693 569 ../functions/number_fields/nfbasistoalg 1793444342 342 ../functions/number_fields/nfdetint 31360921 849 ../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 3143979516 507 ../functions/number_fields/nfeltval 662519148 1467 ../functions/number_fields/nffactor 973653093 818 ../functions/number_fields/nffactorback 3478808850 938 ../functions/number_fields/nffactormod 1084425006 2220 ../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 3510038177 7315 ../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 3390278496 554 ../functions/number_fields/nfsolvemodpr 2732061843 972 ../functions/number_fields/nfsubfields 2786461484 2946 ../functions/number_fields/polcompositum 1916986602 4145 ../functions/number_fields/polgalois 495716662 1934 ../functions/number_fields/polred 575162251 3064 ../functions/number_fields/polredabs 217516956 533 ../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 567059885 576 ../functions/number_fields/rnfcharpoly 1902159865 1094 ../functions/number_fields/rnfconductor 493784289 3512 ../functions/number_fields/rnfdedekind 2250737713 235 ../functions/number_fields/rnfdet 3226307783 779 ../functions/number_fields/rnfdisc 888293248 485 ../functions/number_fields/rnfeltabstorel 2168981093 611 ../functions/number_fields/rnfeltdown 3717382979 642 ../functions/number_fields/rnfeltreltoabs 3578489914 594 ../functions/number_fields/rnfeltup 2244314185 1593 ../functions/number_fields/rnfequation 3457630168 562 ../functions/number_fields/rnfhnfbasis 4078630432 704 ../functions/number_fields/rnfidealabstorel 3893662533 468 ../functions/number_fields/rnfidealdown 1043457146 475 ../functions/number_fields/rnfidealhnf 2972910198 410 ../functions/number_fields/rnfidealmul 2733298389 541 ../functions/number_fields/rnfidealnormabs 2138760702 428 ../functions/number_fields/rnfidealnormrel 4090779943 679 ../functions/number_fields/rnfidealreltoabs 3572608050 463 ../functions/number_fields/rnfidealtwoelt 1231182132 650 ../functions/number_fields/rnfidealup 3243998589 3359 ../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 2726532584 535 ../functions/number_fields/rnfpolred 3396936159 1458 ../functions/number_fields/rnfpolredabs 2300324313 858 ../functions/number_fields/rnfpseudobasis 4120760786 981 ../functions/number_fields/rnfsteinitz 3857332923 2021 ../functions/number_fields/subgrouplist 3758453012 2039 ../functions/number_fields/zetak 2564195553 1135 ../functions/number_fields/zetakinit 215042210 749 ../functions/number_theoretical/addprimes 3938753411 2750 ../functions/number_theoretical/bestappr 691604594 972 ../functions/number_theoretical/bezout 677999113 449 ../functions/number_theoretical/bezoutres 2509326202 632 ../functions/number_theoretical/bigomega 590656338 526 ../functions/number_theoretical/binomial 2799973505 1058 ../functions/number_theoretical/chinese 686535871 1031 ../functions/number_theoretical/content 1721333311 2932 ../functions/number_theoretical/contfrac 520178271 732 ../functions/number_theoretical/contfracpnqn 1215033860 661 ../functions/number_theoretical/core 498340475 1129 ../functions/number_theoretical/coredisc 4003493065 334 ../functions/number_theoretical/dirdiv 3581471294 1153 ../functions/number_theoretical/direuler 418145044 689 ../functions/number_theoretical/dirmul 3382938550 627 ../functions/number_theoretical/divisors 1060604446 531 ../functions/number_theoretical/eulerphi 1092237447 5044 ../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 2764098179 2082 ../functions/number_theoretical/factorint 4224377394 813 ../functions/number_theoretical/factormod 3566569069 537 ../functions/number_theoretical/ffgen 2232547945 566 ../functions/number_theoretical/ffinit 2771022021 1204 ../functions/number_theoretical/fflog 1875050547 861 ../functions/number_theoretical/fforder 1640799602 1120 ../functions/number_theoretical/ffprimroot 641658465 176 ../functions/number_theoretical/fibonacci 977040771 2303 ../functions/number_theoretical/gcd 514753190 536 ../functions/number_theoretical/hilbert 3038340916 463 ../functions/number_theoretical/isfundamental 3013969901 1221 ../functions/number_theoretical/ispower 3017578398 2646 ../functions/number_theoretical/isprime 2569893220 1562 ../functions/number_theoretical/ispseudoprime 233398554 1564 ../functions/number_theoretical/issquare 656619132 546 ../functions/number_theoretical/issquarefree 292278755 800 ../functions/number_theoretical/kronecker 3492197658 1446 ../functions/number_theoretical/lcm 3441815237 448 ../functions/number_theoretical/moebius 1095528473 676 ../functions/number_theoretical/nextprime 2039825979 524 ../functions/number_theoretical/numbpart 699828528 420 ../functions/number_theoretical/numdiv 2363930187 613 ../functions/number_theoretical/omega 4166215275 924 ../functions/number_theoretical/partitions 3412010667 1219 ../functions/number_theoretical/polrootsff 1011544187 691 ../functions/number_theoretical/precprime 3586156342 211 ../functions/number_theoretical/prime 4103257564 345 ../functions/number_theoretical/primepi 3604242667 427 ../functions/number_theoretical/primes 2798669539 2553 ../functions/number_theoretical/qfbclassno 3148474427 356 ../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 63093180 2860 ../functions/number_theoretical/quadclassunit 411309927 217 ../functions/number_theoretical/quaddisc 4137872200 445 ../functions/number_theoretical/quadgen 1926712746 577 ../functions/number_theoretical/quadhilbert 4157827342 422 ../functions/number_theoretical/quadpoly 376107392 612 ../functions/number_theoretical/quadray 3392391708 376 ../functions/number_theoretical/quadregulator 426124966 575 ../functions/number_theoretical/quadunit 3397278150 476 ../functions/number_theoretical/removeprimes 3918764583 828 ../functions/number_theoretical/sigma 290111674 292 ../functions/number_theoretical/sqrtint 3464175627 1336 ../functions/number_theoretical/stirling 1102505332 332 ../functions/number_theoretical/sumdedekind 110444802 2243 ../functions/number_theoretical/zncoppersmith 944496796 1767 ../functions/number_theoretical/znlog 2737149070 769 ../functions/number_theoretical/znorder 390200386 944 ../functions/number_theoretical/znprimroot 2767325332 707 ../functions/number_theoretical/znstar 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 3465962991 346 ../functions/operators/vecmax 540085020 346 ../functions/operators/vecmin 3728482663 863 ../functions/polynomials/O 542241653 848 ../functions/polynomials/deriv 3783180479 1942 ../functions/polynomials/diffop 2324421534 804 ../functions/polynomials/eval 636364238 887 ../functions/polynomials/factorpadic 1978480329 628 ../functions/polynomials/intformal 481866274 642 ../functions/polynomials/padicappr 3969259168 1837 ../functions/polynomials/padicfields 454978205 1173 ../functions/polynomials/polchebyshev 3516775874 1059 ../functions/polynomials/polcoeff 2417687862 899 ../functions/polynomials/polcyclo 2540383469 797 ../functions/polynomials/poldegree 1629390302 482 ../functions/polynomials/poldisc 1885087402 528 ../functions/polynomials/poldiscreduced 1089447095 1136 ../functions/polynomials/polhensellift 2042242352 534 ../functions/polynomials/polhermite 3350225564 749 ../functions/polynomials/polinterpolate 3932442263 460 ../functions/polynomials/polisirreducible 4266292747 609 ../functions/polynomials/pollead 693228044 460 ../functions/polynomials/pollegendre 803988097 240 ../functions/polynomials/polrecip 471183628 1179 ../functions/polynomials/polresultant 2209701456 1387 ../functions/polynomials/polroots 862327389 845 ../functions/polynomials/polrootsmod 355440126 780 ../functions/polynomials/polrootspadic 3644766318 523 ../functions/polynomials/polsturm 2778553936 745 ../functions/polynomials/polsubcyclo 1076716398 656 ../functions/polynomials/polsylvestermatrix 368684839 285 ../functions/polynomials/polsym 686897660 373 ../functions/polynomials/poltchebi 2974829760 714 ../functions/polynomials/polzagier 3084901600 333 ../functions/polynomials/serconvol 678736819 330 ../functions/polynomials/serlaplace 1948396863 253 ../functions/polynomials/serreverse 1472934463 1070 ../functions/polynomials/subst 1374933613 1103 ../functions/polynomials/substpol 2817986031 662 ../functions/polynomials/substvec 226826326 702 ../functions/polynomials/taylor 108370981 2267 ../functions/polynomials/thue 3192854193 993 ../functions/polynomials/thueinit 3300553752 136 ../functions/programming/_eval_mnemonic 3609914548 884 ../functions/programming/addhelp 4205756670 709 ../functions/programming/alarm 164541180 1843 ../functions/programming/alias 37973751 1766 ../functions/programming/allocatemem 1096965433 1180 ../functions/programming/apply 1649867724 490 ../functions/programming/break 673969152 1794 ../functions/programming/default 2638682935 637 ../functions/programming/error 1852833943 400 ../functions/programming/extern 2658094063 458 ../functions/programming/externstr 1154955545 285 ../functions/programming/for 1930174191 1067 ../functions/programming/fordiv 1170627467 583 ../functions/programming/forell 2643836481 921 ../functions/programming/forprime 4097689279 583 ../functions/programming/forstep 2934985242 1834 ../functions/programming/forsubgroup 1571023900 1310 ../functions/programming/forvec 4278770330 361 ../functions/programming/getheap 3575456435 442 ../functions/programming/getrand 4109487323 285 ../functions/programming/getstack 2541612708 336 ../functions/programming/gettime 551521830 165 ../functions/programming/global 1246236981 1504 ../functions/programming/if 1949270646 754 ../functions/programming/input 3426918742 1981 ../functions/programming/install 2467288771 1469 ../functions/programming/kill 3065531026 125 ../functions/programming/local 2557836032 115 ../functions/programming/my 1218387207 521 ../functions/programming/next 1811616303 333 ../functions/programming/print 3073867138 437 ../functions/programming/print1 3605500215 7805 ../functions/programming/printf 1208643084 604 ../functions/programming/printtex 203110110 447 ../functions/programming/quit 1497408310 835 ../functions/programming/read 2278186691 967 ../functions/programming/readvec 1182439920 287 ../functions/programming/return 3178815571 1333 ../functions/programming/select 3452942428 504 ../functions/programming/setrand 93155116 409 ../functions/programming/system 1079001113 2110 ../functions/programming/trap 722695522 608 ../functions/programming/type 3467212281 421 ../functions/programming/until 1261987087 1824 ../functions/programming/version 1821695084 505 ../functions/programming/warning 1594674442 434 ../functions/programming/whatnow 3282345452 395 ../functions/programming/while 559370645 305 ../functions/programming/write 3083331806 313 ../functions/programming/write1 509683179 1963 ../functions/programming/writebin 3395311360 248 ../functions/programming/writetex 3647513843 1024 ../functions/sums/derivnum 847633432 836 ../functions/sums/intcirc 675879057 862 ../functions/sums/intfouriercos 3481939193 904 ../functions/sums/intfourierexp 3947097796 857 ../functions/sums/intfouriersin 2886318425 1557 ../functions/sums/intfuncinit 3456264235 2300 ../functions/sums/intlaplaceinv 2519244525 2071 ../functions/sums/intmellininv 1440289081 2077 ../functions/sums/intmellininvshort 3887391742 12018 ../functions/sums/intnum 1762228811 1941 ../functions/sums/intnuminit 2969886763 974 ../functions/sums/intnuminitgen 2565352605 2665 ../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 4184221123 692 ../functions/sums/sumdiv 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 587207606 763 ../functions/symbolic_operators/coeff 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 714839643 1195 ../functions/symbolic_operators/eq 57471919 155 ../functions/symbolic_operators/fact 686849312 736 ../functions/symbolic_operators/ge 3422426820 725 ../functions/symbolic_operators/gt 1679693701 104 ../functions/symbolic_operators/hist 4154293089 124 ../functions/symbolic_operators/id 484987478 795 ../functions/symbolic_operators/le 830285697 725 ../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 383177618 1040 ../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 1327651723 238 ../functions/symbolic_operators/shiftl 2222950945 363 ../functions/symbolic_operators/shiftle 540758560 300 ../functions/symbolic_operators/shiftr 3408057925 372 ../functions/symbolic_operators/shiftre 3996600320 112 ../functions/symbolic_operators/store 1170897255 771 ../functions/symbolic_operators/sub 3687286192 892 ../functions/symbolic_operators/sube 3333748126 198 ../functions/symbolic_operators/trans 3314164466 396 ../functions/transcendental/Euler 4128767667 143 ../functions/transcendental/I 3490942501 207 ../functions/transcendental/Pi 3536365179 841 ../functions/transcendental/abs 2484349986 482 ../functions/transcendental/acos 3003347379 368 ../functions/transcendental/acosh 3852344871 457 ../functions/transcendental/agm 2673702082 198 ../functions/transcendental/arg 2799632495 484 ../functions/transcendental/asin 453402835 364 ../functions/transcendental/asinh 1571898858 473 ../functions/transcendental/atan 1511318290 333 ../functions/transcendental/atanh 3784737751 311 ../functions/transcendental/bernfrac 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 2359045432 135 ../functions/transcendental/cosh 3039924894 124 ../functions/transcendental/cotan 3749138764 232 ../functions/transcendental/dilog 4225776774 538 ../functions/transcendental/eint1 4281803296 226 ../functions/transcendental/erfc 1932581236 1106 ../functions/transcendental/eta 4186273876 387 ../functions/transcendental/exp 348198190 808 ../functions/transcendental/gamma 1095695996 169 ../functions/transcendental/gammah 1703809654 306 ../functions/transcendental/hyperu 46677349 567 ../functions/transcendental/incgam 1394040053 409 ../functions/transcendental/incgamc 415957404 396 ../functions/transcendental/lngamma 3393608858 1090 ../functions/transcendental/log 2637087612 1600 ../functions/transcendental/polylog 1895228131 188 ../functions/transcendental/psi 1520878203 108 ../functions/transcendental/sin 567709619 131 ../functions/transcendental/sinh 473305427 963 ../functions/transcendental/sqr 4000285325 813 ../functions/transcendental/sqrt 1151073196 1519 ../functions/transcendental/sqrtn 1255385460 114 ../functions/transcendental/tan 1062239263 137 ../functions/transcendental/tanh 4246144284 278 ../functions/transcendental/teichmuller 2713807692 227 ../functions/transcendental/theta 3682432533 352 ../functions/transcendental/thetanullk 2007207279 1064 ../functions/transcendental/weber 298482603 822 ../functions/transcendental/zeta pari-2.5.5/src/functions/0000755000175000017500000000000012212611624013700 5ustar billbillpari-2.5.5/src/functions/operators/0000755000175000017500000000000012212611624015716 5ustar billbillpari-2.5.5/src/functions/operators/max0000644000175000017500000000104411636712103016430 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.5.5/src/functions/operators/min0000644000175000017500000000104411636712103016426 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.5.5/src/functions/operators/lex0000644000175000017500000000155311636712103016440 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.5.5/src/functions/operators/vecmax0000644000175000017500000000053212147140046017126 0ustar billbillFunction: vecmax Section: operators C-Name: vecmax Prototype: G Help: vecmax(x): maximum of the elements of the vector/matrix x Doc: if $x$ is a vector or a matrix, returns the maximum of the elements of $x$, otherwise returns a copy of $x$. Error if $x$ is empty. Description: (vecsmall):small vecsmall_max($1) (gen):gen vecmax($1) pari-2.5.5/src/functions/operators/vecmin0000644000175000017500000000053212147140046017124 0ustar billbillFunction: vecmin Section: operators C-Name: vecmin Prototype: G Help: vecmin(x): minimum of the elements of the vector/matrix x Doc: if $x$ is a vector or a matrix, returns the minimum of the elements of $x$, otherwise returns a copy of $x$. Error if $x$ is empty. Description: (vecsmall):small vecsmall_min($1) (gen):gen vecmin($1) pari-2.5.5/src/functions/operators/sign0000644000175000017500000000044311636712103016605 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.5.5/src/functions/operators/divrem0000644000175000017500000000214011636712103017127 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.5.5/src/functions/operators/shift0000644000175000017500000000104611636712103016762 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.5.5/src/functions/operators/shiftmul0000644000175000017500000000065011636712103017500 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.5.5/src/functions/default/0000755000175000017500000000000012212611624015324 5ustar billbillpari-2.5.5/src/functions/default/debug0000644000175000017500000000041011636712103016333 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.5.5/src/functions/default/datadir0000644000175000017500000000057411636712103016670 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.5.5/src/functions/default/graphcolormap0000644000175000017500000000177012147140046020114 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{"antique white"} represent the same color. RGB codes are a little 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.5.5/src/functions/default/compatible0000644000175000017500000000425411636712103017376 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 favourite 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.5.5/src/functions/default/seriesprecision0000644000175000017500000000040111636712103020453 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.5.5/src/functions/default/prettyprinter0000644000175000017500000000061311636712103020205 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.5.5/src/functions/default/logfile0000644000175000017500000000037111636712103016674 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.5.5/src/functions/default/recover0000644000175000017500000000047011636712103016720 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.5.5/src/functions/default/strictmatch0000644000175000017500000000073011636712103017577 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.5.5/src/functions/default/TeXstyle0000644000175000017500000000100411636712103017026 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.5.5/src/functions/default/log0000644000175000017500000000140611636712103016034 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.5.5/src/functions/default/realprecision0000644000175000017500000000135512147140046020114 0ustar billbillFunction: _def_realprecision Class: default Section: default C-Name: sd_realprecision Prototype: Help: Doc: \subsecidx{realprecision} : the number of significant digits and, at the same time, the number of printed digits of real numbers (see~\b{p}). Note that PARI internal precision works on a word basis (32 or 64 bits), hence may not coincide with the number of decimal digits you input. For instance to get 2 decimal digits you need one word of precision which, on a 32-bit machine, actually gives you 9 digits ($9 < \log_{10}(2^{32}) < 10$): \bprog ? default(realprecision, 2) realprecision = 9 significant digits (2 digits displayed) @eprog The default value is \kbd{28}, resp.~\kbd{38} on a 32-bit, resp~.64-bit, machine. pari-2.5.5/src/functions/default/psfile0000644000175000017500000000047511636712103016542 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.5.5/src/functions/default/help0000644000175000017500000000061111636712103016200 0ustar billbillFunction: _def_help Class: gp_default Section: default C-Name: sd_help Prototype: Help: Doc: name of the external help program which will be used 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 local of the \kbd{gphelp} script. pari-2.5.5/src/functions/default/histsize0000644000175000017500000000067311636712103017122 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.5.5/src/functions/default/path0000644000175000017500000000131011636712103016201 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.5.5/src/functions/default/format0000644000175000017500000000260211636712103016542 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.5.5/src/functions/default/factor_proven0000644000175000017500000000123711636712103020124 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 defaut value is \kbd{0}. pari-2.5.5/src/functions/default/echo0000644000175000017500000000072411636712103016173 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.5.5/src/functions/default/new_galois_format0000644000175000017500000000072311636712103020753 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 defaut value is \kbd{0}. This value will change to $1$ (set) in the next major version. pari-2.5.5/src/functions/default/debugmem0000644000175000017500000000111711636712103017037 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.5.5/src/functions/default/prompt0000644000175000017500000000265411636712103016602 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.5.5/src/functions/default/graphcolors0000644000175000017500000000062311636712103017576 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.5.5/src/functions/default/factor_add_primes0000644000175000017500000000140511636712103020717 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 defaut value is \kbd{0}. pari-2.5.5/src/functions/default/lines0000644000175000017500000000105411636712103016364 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.5.5/src/functions/default/debugfiles0000644000175000017500000000046311636712103017366 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.5.5/src/functions/default/colors0000644000175000017500000000422211636712103016553 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 $\bullet$ the keyword \kbd{no} (use the default color, usually black on transparent background) \noindent $\bullet$ an integer between 0 and 15 corresponding to the aforementioned colormap \noindent $\bullet$ 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.5.5/src/functions/default/prompt_cont0000644000175000017500000000053511636712103017621 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 defaut value is \kbd{""}. pari-2.5.5/src/functions/default/readline0000644000175000017500000000066611636712103017045 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.5.5/src/functions/default/simplify0000644000175000017500000000154411636712103017112 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.5.5/src/functions/default/histfile0000644000175000017500000000106211636712103017060 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.5.5/src/functions/default/timer0000644000175000017500000000071212147140046016371 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). If on, every instruction sequence (anything ended by a newline in your input) is timed, to some accuracy depending on the hardware and operating system. The time measured is the user \idx{CPU time}, \emph{not} including the time for printing the results (see \kbd{\#} and \kbd{\#\#}). The default value is \kbd{0}. pari-2.5.5/src/functions/default/primelimit0000644000175000017500000000130512147140046017423 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. These are used by many arithmetic functions, usually for trial division purposes. If you do not plan to invoke any of them, you can just set this to 1. The maximal value is a little less than $2^{32}$ (resp $2^{64}$) on a 32-bit (resp.~64-bit) machine. Since almost all arithmetic functions eventually require some table of prime numbers, PARI currently guarantees that the first 6547 primes, up to and including 65557, are precomputed, even if \kbd{primelimit} is $1$. The default value is \kbd{500k}. pari-2.5.5/src/functions/default/secure0000644000175000017500000000071011636712103016536 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.5.5/src/functions/default/breakloop0000644000175000017500000000044311636712103017231 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.5.5/src/functions/default/parisize0000644000175000017500000000131011636712103017073 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.5.5/src/functions/default/output0000644000175000017500000000260711636712103016617 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: $\bullet$ \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. $\bullet$ \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. $\bullet$ \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.5.5/src/functions/elliptic_curves/0000755000175000017500000000000012212611624017074 5ustar billbillpari-2.5.5/src/functions/elliptic_curves/ellinit0000644000175000017500000000771312147140046020471 0ustar billbillFunction: ellinit Section: elliptic_curves C-Name: ellinit0 Prototype: GD0,L,p Help: ellinit(x,{flag=0}): x being the vector [a1,a2,a3,a4,a6] defining the curve Y^2 + a1.XY + a3.Y = X^3 + a2.X^2 + a4.X + a6, gives the vector: [a1,a2,a3,a4,a6,b2,b4,b6,b8,c4,c6,disc,j,[e1,e2,e3],w1,w2,eta1,eta2,area]. If the curve is defined over a p-adic field, the last six components are replaced by root,u^2,u,q,w,0. If optional flag is 1, omit them altogether. x can also be a string, in this case the coefficients of the curve with matching name are looked in the elldata database if available. Description: (gen, ?0):bell:prec ellinit($1, prec) (gen, 1):ell smallellinit($1) (gen, small):ell:prec ellinit0($1, $2, prec) Doc: initialize an \tet{ell} structure, associated to the elliptic curve $E$. $E$ is either 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 $$ or a string, in this case the coefficients of the curve with matching name are looked in the \tet{elldata} database if available. \bprog ? E = ellinit([0,0,0,0,1]); \\ y^2 = x^3 + 1 ? E = ellinit("36a1"); \\ the same curve, using Cremona's notations @eprog\noindent For the time being, only curves over a prime field $\F_p$ and over the $p$-adic or real numbers (including rational numbers) are fully supported. Other domains are only supported for very basic operations such as point addition. The result of \tet{ellinit} is an \tev{ell} structure by default, and a shorter \tev{sell} if $\fl=1$. Both contain the following information in their 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}. The other six components are only present if $\fl$ is $0$ or omitted, in which case the computation will be 10 ($p$-adic) to 200 (complex) times slower. Their content depends on whether the curve is defined over $\R$ or not: \smallskip \item When $E$ is defined over $\R$, \kbd{$E$.roots} is a vector whose three components contain the roots of the right hand side of the associated Weierstrass equation. $$ (y + a_1x/2 + a_3/2)^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. Then $\omega_1 = $\kbd{$E$.omega[1]} is the real period of $E$ (integral of $dx/(2y+a_1x+a_3)$ over the connected component of the identity element of the real points of the curve), and $\omega_2 = $\kbd{$E$.omega[2]} is a complex period. \kbd{$E$.omega} forms a basis of the complex lattice defining $E$, such that $\tau=\dfrac{\omega_1}{\omega_2}$ has positive imaginary part. \kbd{$E$.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$. Finally, \kbd{$E$.area} is the volume of the complex lattice defining $E$.\smallskip \item When $E$ is defined over $\Q_p$, the $p$-adic valuation of $j$ must be negative. Then \kbd{$E$.roots} is the vector with a single component equal to the $p$-adic root of the associated Weierstrass equation corresponding to $-1$ under the Tate parametrization. \kbd{$E$.tate} yields the three-component vector $[u^2,u,q]$, in the notations of Tate. If the $u$-component does not belong to $\Q_p$, it is set to zero. \kbd{$E$.w} is Mestre's $w$ (this is technical). \smallskip For all other base fields or rings, the last six components are arbitrarily set to zero. See also the description of member functions related to elliptic curves at the beginning of this section. Variant: Also available are \fun{GEN}{ellinit}{GEN E, long prec} ($\fl=0$) and \fun{GEN}{smallellinit}{GEN E, long prec} ($\fl=1$). pari-2.5.5/src/functions/elliptic_curves/ellwp0000644000175000017500000000230012147140046020137 0ustar billbillFunction: ellwp Section: elliptic_curves C-Name: ellwp0 Prototype: GDGD0,L,DPp Help: ellwp(E,{z=x},{flag=0},{d=seriesprecision}): computes the value at z of the Weierstrass P function attached to the elliptic curve E as given by ellinit (alternatively, E can be given as a lattice [om1,om2]). Optional flag means 0 (default), compute only P(z), 1 compute [P(z),P'(z)], 2 consider om as an elliptic curve and compute P(z) for that curve (identical to ellztopoint in that case). If z is omitted or is a simple variable, return formal expansion in z with d significant terms. Doc: Computes the value at $z$ of the Weierstrass $\wp$ function attached to the elliptic curve $E$ as given by \kbd{ellinit} (alternatively, $E$ can be given as a lattice $[\omega_1,\omega_2]$). If $z$ is omitted or is a simple variable, computes the \emph{power series} expansion in $z$ (starting $z^{-2}+O(z^2)$). The series is given to $d$ significant terms (\tet{seriesprecision} by default). Optional \fl\ is (for now) only taken into account when $z$ is numeric, and means 0: compute only $\wp(z)$, 1: compute $[\wp(z),\wp'(z)]$. Variant: Also available is \fun{GEN}{weipell}{GEN E, long precdl} for the power series. pari-2.5.5/src/functions/elliptic_curves/ellheight0000644000175000017500000000176712147140046021001 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 (assumed to be a minimal model). 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 \idx{N\'eron-Tate height} of the point $z$ on the elliptic curve $E$ (defined over $\Q$), given by a standard minimal integral model. $E$ must be an \kbd{ell} as output by \kbd{ellinit}. \fl selects the algorithm used to compute the Archimedean local height. If $\fl=0$, this computation is done using sigma and theta-functions and a trick due to J.~Silverman. If $\fl=1$, use Tate's $4^n$ algorithm. If $\fl=2$, use Mestre's AGM algorithm. The latter is much faster than the other two, both in theory (converges quadratically) and in practice. Variant: Also available is \fun{GEN}{ghell}{GEN E, GEN x, long prec} ($\fl=2$). pari-2.5.5/src/functions/elliptic_curves/ellheightmatrix0000644000175000017500000000143511636712103022217 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, assume to be a minimal model. 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 that this matrix should be divided by 2 to be in accordance with certain normalizations. $E$ is assumed to be integral, given by a minimal model. pari-2.5.5/src/functions/elliptic_curves/ellsearch0000644000175000017500000000202411636712103020762 0ustar billbillFunction: ellsearch Section: elliptic_curves C-Name: ellsearch Prototype: G Help: ellsearch(N): if N is an integer, it is taken as a conductor else if N is a string, it can be a curve name ("11a1"), a isogeny class ("11a") or a conductor ("11"). Return all curves in the elldata database that match the property. Doc: if $N$ is an integer, it is taken as a conductor else if $N$ is a string, it can be a curve name ("11a1"), an isogeny class ("11a") or a conductor "11". This function finds all curves in the \tet{elldata} database with the given property. If $N$ is a full curve name, 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. If $N$ is not a full-curve name, the output is a vector of all matching curves in the above format. Variant: Also available is \fun{GEN}{ellsearchcurve}{GEN N} that only accepts complete curve names. pari-2.5.5/src/functions/elliptic_curves/ellminimalmodel0000644000175000017500000000141611636712103022170 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.5.5/src/functions/elliptic_curves/ellanalyticrank0000644000175000017500000000214611636712103022202 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.5.5/src/functions/elliptic_curves/ellak0000644000175000017500000000144512147140046020115 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 a minimal model). Doc: computes the coefficient $a_n$ of the $L$-function of the elliptic curve $E$, i.e.~in principle coefficients of a newform of weight 2 assuming \idx{Taniyama-Weil conjecture} (which is now known to hold in full generality thanks to the work of \idx{Breuil}, \idx{Conrad}, \idx{Diamond}, \idx{Taylor} and \idx{Wiles}). $E$ must be a \var{smallell} as output by \kbd{ellinit}. For this function to work for every $n$ and not just those prime to the conductor, $E$ must be a minimal Weierstrass equation. If this is not the case, use the function \kbd{ellminimalmodel} before using \kbd{ellak}. pari-2.5.5/src/functions/elliptic_curves/ellgenerators0000644000175000017500000000107312147140046021670 0ustar billbillFunction: ellgenerators Section: elliptic_curves C-Name: ellgenerators Prototype: G Help: ellgenerators(E): if E is an elliptic curve as output by ellinit(), return the generators of the Mordell-Weil group associated to the curve. This function depends on the curve being referenced in the elldata database. Doc: returns a $\Z$-basis of the free part of the \idx{Mordell-Weil group} associated to $E$. This function depends on the \tet{elldata} database being installed and referencing the curve, and so is only available for curves over $\Z$ of small conductors. pari-2.5.5/src/functions/elliptic_curves/ellj0000644000175000017500000000043111636712103017746 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.5.5/src/functions/elliptic_curves/ellpow0000644000175000017500000000205212147140046020322 0ustar billbillFunction: ellpow Section: elliptic_curves C-Name: powell Prototype: GGG Help: ellpow(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([0,0,0,1,0]); z = [0,0]; ? ellpow(Ei, z, 10) %2 = [0] \\ unsurprising: z has order 2 ? ellpow(Ei, z, I) %3 = [0, 0] \\ Ei has complex multiplication by Z[i] ? ellpow(Ei, z, quadgen(-4)) %4 = [0, 0] \\ an alternative syntax for the same query ? Ej = ellinit([0,0,0,0,1]); z = [-1,0]; ? ellpow(Ej, z, I) *** at top-level: ellpow(Ej,z,I) *** ^-------------- *** ellpow: not a complex multiplication in powell. ? ellpow(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.5.5/src/functions/elliptic_curves/elleta0000644000175000017500000000116512147140046020272 0ustar billbillFunction: elleta Section: elliptic_curves C-Name: elleta Prototype: Gp Help: elleta(om): om=[om1,om2], returns the two-component row vector [eta1,eta2] of quasi-periods associated to [om1,om2]. Doc: returns the quasi-periods $[\eta_1,\eta_2]$ associated to the lattice basis $\var{om} = [\omega_1, \omega_2]$. Alternatively, \var{om} 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.5.5/src/functions/elliptic_curves/ellisoncurve0000644000175000017500000000113211636712103021531 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.5.5/src/functions/elliptic_curves/elllog0000644000175000017500000000204612147140046020301 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: discrete logarithm of the point $P$ of the elliptic curve $E$ in base $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 = ellpow(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 ? ellpow(E,G,e) == P %6 = 1 @eprog pari-2.5.5/src/functions/elliptic_curves/elldivpol0000644000175000017500000000035712147140046021020 0ustar billbillFunction: elldivpol Section: elliptic_curves C-Name: elldivpol Prototype: GLDn Help: elldivpol(E,n,{v='x}): n-division polynomial for the curve E in the variable v. Doc: $n$-division polynomial for the curve \kbd{E} in the variable $v$. pari-2.5.5/src/functions/elliptic_curves/elllseries0000644000175000017500000000136612147140046021172 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 \var{sell} as output by \kbd{ellinit}, this computes the value of the L-series of $E$ at $s$. It is assumed that $E$ is defined over $\Q$, not necessarily minimal. The optional parameter $A$ is a cutoff point for the integral, which must be chosen close to 1 for best speed. The result must be independent of $A$, so this allows some internal checking of the function. Note that if the conductor of the curve is large, say greater than $10^{12}$, this function will take an unreasonable amount of time since it uses an $O(N^{1/2})$ algorithm. pari-2.5.5/src/functions/elliptic_curves/ellsigma0000644000175000017500000000160712147140046020622 0ustar billbillFunction: ellsigma Section: elliptic_curves C-Name: ellsigma Prototype: GGD0,L,p Help: ellsigma(E,z,{flag=0}): E being given by ellinit, returns the value of the Weierstrass sigma function of the lattice generated by om at z if flag = 0 (default). If flag = 1, arbitrary determination of the logarithm of sigma. If flag = 2 or 3, same but using the product expansion instead of theta series. Doc: $E$ being given by \kbd{ellinit}, returns the value at $z$ of the Weierstrass $\sigma$ function of the period lattice $L$ of $E$: $$ \sigma(z, L) = z \prod_{\omega\in L^*} \left(1 - \dfrac{z}{\omega}\right)e^{\dfrac{z}{\omega} + \dfrac{z^2}{2\omega^2}}$$ Alternatively, one can input a lattice basis $[\omega_1,\omega_2]$ directly instead of $E$. If $\fl=1$, computes an (arbitrary) determination of $\log(\sigma(z))$. If $\fl=2,3$, same using the product expansion instead of theta series. pari-2.5.5/src/functions/elliptic_curves/ellglobalred0000644000175000017500000000166412147140046021460 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], 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. 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 a \var{smallell} as output by \kbd{ellinit}, \emph{and is supposed to have all its coefficients $a_i$ in} $\Q$. The result is a 3 component vector $[N,v,c]$. $N$ is the arithmetic conductor of the curve. $v$ gives the coordinate change for $E$ over $\Q$ to the minimal integral model (see \tet{ellminimalmodel}). Finally $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} pari-2.5.5/src/functions/elliptic_curves/ellmodulareqn0000644000175000017500000000110112147140046021656 0ustar billbillFunction: ellmodulareqn Section: elliptic_curves C-Name: ellmodulareqn Prototype: LDnDn Help: ellmodulareqn(l,{x},{y}): return a vector [eqn, t] where eqn is a modular equation of level l, for l<500, l 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 $l$, for $l<500$, $l$ prime. This requires the package seadata to be installed. The equation is either of canonical type ($t=0$) or of Atkin type ($t=1$). pari-2.5.5/src/functions/elliptic_curves/ellrootno0000644000175000017500000000124612147140046021041 0ustar billbillFunction: ellrootno Section: elliptic_curves C-Name: ellrootno Prototype: lGDG Help: ellrootno(E,{p=1}): root number for the L-function of the elliptic curve E. p can be 1 (default), global root number, or a prime p (including 0) for the local root number at p. Doc: $E$ being a \var{smallell} as output by \kbd{ellinit}, this computes the local (if $p\neq 1$) or global (if $p=1$) root number of the L-series of the elliptic curve $E$. 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$ must have coefficients in $\Q$ but need \emph{not} be minimal. pari-2.5.5/src/functions/elliptic_curves/ellan0000644000175000017500000000053412147140046020116 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$ $a_k$ corresponding to the elliptic curve $E$. All comments in \kbd{ellak} description remain valid. pari-2.5.5/src/functions/elliptic_curves/ellbil0000644000175000017500000000114311636712103020264 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 (assumed to be minimal). Either z1 or z2 can also be a vector/matrix of points. Doc: if $z1$ and $z2$ are points on the elliptic curve $E$, assumed to be integral given by a minimal model, 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.5.5/src/functions/elliptic_curves/ellsub0000644000175000017500000000036112147140046020307 0ustar billbillFunction: ellsub Section: elliptic_curves C-Name: subell 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.5.5/src/functions/elliptic_curves/ellgroup0000644000175000017500000000211112147140046020645 0ustar billbillFunction: ellgroup Section: elliptic_curves C-Name: ellgroup Prototype: GDG Help: ellgroup(E,{p}): computes the structure of the group E(Fp) Assume the equation is minimal at p. Doc: computes the structure of the group $E(\F_p) \sim \Z/d_1\Z \times \Z/d_2\Z$, with $d_2\mid d_1$. The prime $p$ may be omitted if the curve was defined over $\F_p$ (\typ{INTMOD} coefficients) or $\Q_p$ (\typ{PADIC} coefficients). Otherwise the curve must be defined over $\Q$, and $p$ must be explicitly given. Over $\Q$ or $\Q_p$, the equation is assumed to be minimal at $p$. \bprog ? E = ellinit([0,0,0,0,1]); \\ defined over Q ? ellgroup(E, 3) \\ 3 necessary here %2 = [4] \\ cyclic ? ellgroup(E, 7) %3 = [6, 2] \\ non-cyclic ? E = ellinit([0,0,0,0,1] * Mod(1,11)); \\ defined over F_11 ? ellgroup(E) \\ no need to repeat 11 %5 = [12] ? ellgroup(E, 11) \\ ... but it also works %6 = [12] ? ellgroup(E, 13) \\ ouch, inconsistent input ! *** at top-level: ellgroup(E,13) *** ^-------------- *** ellgroup: inconsistent moduli in Rg_to_Fp: 11, 13. @eprog pari-2.5.5/src/functions/elliptic_curves/ellchangepoint0000644000175000017500000000103112147140046022010 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}). Variant: The reciprocal function \fun{GEN}{ellchangepointinv}{GEN x, GEN ch} inverts the coordinate change. pari-2.5.5/src/functions/elliptic_curves/elltaniyama0000644000175000017500000000206612147140046021325 0ustar billbillFunction: elltaniyama Section: elliptic_curves C-Name: elltaniyama Prototype: GDP Help: elltaniyama(E, {d = seriesprecision}): modular parametrization of elliptic curve E (minimal model). Doc: computes the modular parametrization of the elliptic curve $E$, where $E$ is a \var{smallell} as output by \kbd{ellinit}, in the form of a two-component vector $[u,v]$ of power series, given to $d$ significant terms (\tet{seriesprecision} by default). This vector is characterized by the following two properties. First the point $(x,y)=(u,v)$ satisfies the equation of the elliptic curve. Second, the differential $du/(2v+a_1u+a_3)$ is equal to $f(z)dz$, a differential form on $H/\Gamma_0(N)$ where $N$ is the conductor of the curve. 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)$. It is assumed that the curve is a \emph{strong} \idx{Weil curve}, and that the Manin constant is equal to 1. The equation of the curve $E$ must be minimal (use \kbd{ellminimalmodel} to get a minimal equation). pari-2.5.5/src/functions/elliptic_curves/ellap0000644000175000017500000000371612147140046020125 0ustar billbillFunction: ellap Section: elliptic_curves C-Name: ellap Prototype: GDG Help: ellap(E,{p}): computes a_p for the elliptic curve E using Shanks-Mestre's method, or SEA algorithm if the package seadata is installed. Assume the equation is minimal at p. Doc: computes the trace of Frobenius $a_p$ for the elliptic curve $E$ and the prime number $p$. This is defined by the equation $\#E(\F_p) = p+1 - a_p$, where $\#E(\F_p)$ stands for the number of points of the curve $E$ over the finite field $\F_p$. No checking is done that $p$ is indeed prime. $E$ must be a \var{smallell} as output by \kbd{ellinit}, defined over $\Q$, $\Q_p$, or $\F_p$. The prime $p$ may be omitted if the curve was defined over $\F_p$ (\typ{INTMOD} coefficients) or $\Q_p$ (\typ{PADIC} coefficients). Otherwise the curve must be defined over $\Q$, and $p$ must be explicitly given. Over $\Q$ or $\Q_p$, the equation is assumed to be minimal at $p$. \bprog ? E = ellinit([0,0,0,0,1]); \\ defined over Q ? ellap(E, 3) \\ 3 necessary here %2 = 0 \\ #E(F_3) = 3+1 - 0 = 4 ? ellap(E, 7) %3 = -4 \\ #E(F_7) = 12 ? E = ellinit([0,0,0,0,1] * Mod(1,11)); \\ defined over F_11 ? ellap(E) \\ no need to repeat 11 %5 = 0 ? ellap(E, 11) \\ ... but it also works %6 = 0 ? ellgroup(E, 13) \\ ouch, inconsistent input ! *** at top-level: ellap(E,13) *** ^----------- *** ellap: inconsistent moduli in Rg_to_Fp: 11, 13. @eprog \misctitle{Algorithms used} If $E/\F_p$ has CM by a principal imaginary quadratic order we use an explicit formula (involving essentially Kronecker symbols and Cornacchia's algorithm, hence very fast: $O(\log p)^2$). Otherwise, we use Shanks-Mestre's baby-step/giant-step method, which runs in time $O(p^{1/4})$ using $O(p^{1/4})$ storage, hence becomes unreasonable when $p$ has about 30~digits. If the \tet{seadata} package is installed, the \tet{SEA} algorithm becomes available and primes of the order of 200~digits become feasible. pari-2.5.5/src/functions/elliptic_curves/ellorder0000644000175000017500000000230711636712103020634 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 (mandatory over non-prime finite fields). Doc: gives the order of the point $z$ on the elliptic curve $E$. If the curve is defined over $\Q$, return zero if the point has infinite order. The parameter $o$, if present, 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. For a curve defined over $\F_p$, it is very important to supply $o$ since its computation is very expensive and should only be done once, using \bprog ? N = p+1-ellap(E,p); o = [N, factor(N)]; @eprog\noindent possibly using the \tet{seadata} package; for a curve defined over a non-prime finite field, giving the order is \emph{mandatory} since no function is available yet to compute the cardinality or trace of Frobenius in that case. Variant: The obsolete form \fun{GEN}{orderell}{GEN e, GEN z} should no longer be used. pari-2.5.5/src/functions/elliptic_curves/elltors0000644000175000017500000000232312147140046020505 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 Doud's algorithm; if flag = 1, use Lutz-Nagell. 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} as output by \kbd{ellinit}. \bprog ? E = ellinit([0,0,0,-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$, use Doud's algorithm: bound torsion by computing $\#E(\F_p)$ for small primes of good reduction, then look for torsion points using Weierstrass parametrization (and Mazur's classification). If $\fl = 1$, use Lutz-Nagell (\emph{much} slower), $E$ is allowed to be a \var{smallell}. Variant: Also available is \fun{GEN}{elltors}{GEN E} for \kbd{elltors(E, 0)}. pari-2.5.5/src/functions/elliptic_curves/elladd0000644000175000017500000000034312147140046020246 0ustar billbillFunction: elladd Section: elliptic_curves C-Name: addell 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.5.5/src/functions/elliptic_curves/ellidentify0000644000175000017500000000121612147140046021331 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 J. E. Cremona database, M the minimal model and C the coordinates change (see ellchangecurve). Doc: look up the elliptic curve $E$ (over $\Z$) in the \tet{elldata} database and return \kbd{[[N, M, G], C]} where $N$ is the name of the curve in the J.~E.~Cremona database, $M$ the minimal model, $G$ a $\Z$-basis of the free part of the \idx{Mordell-Weil group} of $E$ and $C$ the coordinates change (see \kbd{ellchangecurve}). pari-2.5.5/src/functions/elliptic_curves/ellconvertname0000644000175000017500000000115411636712103022041 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.5.5/src/functions/elliptic_curves/ellordinate0000644000175000017500000000046311636712103021327 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.5.5/src/functions/elliptic_curves/elllocalred0000644000175000017500000000235112147140046021304 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 a \var{smallell} 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. Normally, this has no use if $u$ is 1, that is, if the given equation was already minimal. Finally, the last component $c$ is the local \idx{Tamagawa number} $c_p$. pari-2.5.5/src/functions/elliptic_curves/ellL10000644000175000017500000000262711636712103020002 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.5.5/src/functions/elliptic_curves/ellchangecurve0000644000175000017500000000075112147140046022013 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 a \var{smallell} as output by \kbd{ellinit}. pari-2.5.5/src/functions/elliptic_curves/ellzeta0000644000175000017500000000167312147140046020470 0ustar billbillFunction: ellzeta Section: elliptic_curves C-Name: ellzeta Prototype: GGp Help: ellzeta(E,z): E being given by ellinit, returns the value at z of the Weierstrass zeta function of the period lattice of E. Doc: $E$ being given by \kbd{ellinit}, returns the value at $z$ of the Weierstrass $\zeta$ function of the period lattice $L$ of $E$: $$ \zeta(z, L) = \dfrac{1}{z} + z^2\sum_{\omega\in L^*} \dfrac{1}{\omega^2(z-\omega)}.$$ Alternatively, one can input a lattice basis $[\omega_1,\omega_2]$ directly instead of $E$. \bprog ? e = ellinit([0,0,0,1,0]); ? ellzeta(e, e.omega[1]/2) %2 = 0.8472130847939790866064991234 + 4.417621070 E-29*I ? 2*ellzeta([1,I], 1/2) %3 = 3.141592653589793238462643384 + 0.E-37*I @eprog\noindent 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 directly as $\eta_i = 2\zeta(\omega_i/2)$ or using \tet{elleta}. pari-2.5.5/src/functions/elliptic_curves/ellpointtoz0000644000175000017500000000163612147140046021412 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$ is an elliptic curve with coefficients in $\R$, this computes a complex number $t$ (modulo the lattice defining $E$) corresponding to the point $z$, i.e.~such that, in the standard Weierstrass model, $\wp(t)=z[1],\wp'(t)=z[2]$. In other words, this is the inverse function of \kbd{ellztopoint}. More precisely, if $(w1,w2)$ are the real and complex periods of $E$, $t$ is such that $0 \leq \Re(t) < w1$ and $0 \leq \Im(t) < \Im(w2)$. If $E$ has coefficients in $\Q_p$, then either Tate's $u$ is in $\Q_p$, in which case the output is a $p$-adic number $t$ corresponding to the point $z$ under the Tate parametrization, or only its square is, in which case the output is $t+1/t$. $E$ must be an \var{ell} as output by \kbd{ellinit}. pari-2.5.5/src/functions/elliptic_curves/elleisnum0000644000175000017500000000203712147140046021020 0ustar billbillFunction: elleisnum Section: elliptic_curves C-Name: elleisnum Prototype: GLD0,L,p Help: elleisnum(E,k,{flag=0}): E being an elliptic curve (or, alternatively, given by a 2-component vector representing its periods) and k an even positive integer, computes the numerical value of the Eisenstein series of weight k. When flag is non-zero and k=4 or 6, this gives g2 or g3 with the correct normalization. Doc: $E$ being an elliptic curve as output by \kbd{ellinit} (or, alternatively, given by a 2-component vector $[\omega_1,\omega_2]$ representing its periods), and $k$ being an even positive integer, computes the numerical value of the Eisenstein series of weight $k$ at $E$, 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. 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.5.5/src/functions/elliptic_curves/elltatepairing0000644000175000017500000000055211636712103022030 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.5.5/src/functions/elliptic_curves/ellweilpairing0000644000175000017500000000047611636712103022040 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.5.5/src/functions/elliptic_curves/ellztopoint0000644000175000017500000000115111636712103021403 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, $[x,y]$ represents the \idx{Weierstrass $\wp$-function} and its derivative. If $z$ is in the lattice defining $E$ over $\C$, the result is the point at infinity $[0]$. pari-2.5.5/src/functions/number_fields/0000755000175000017500000000000012212611624016516 5ustar billbillpari-2.5.5/src/functions/number_fields/idealramgroups0000644000175000017500000000251512147140046021464 0ustar billbillFunction: idealramgroups Section: number_fields C-Name: idealramgroups Prototype: GGG Help: idealramgroups(nf,gal,pr): let pr be a prime ideal pr in prid format, in the Galois group gal 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 $nf$ and assume $K/\Q$ be a Galois extension with Galois group $G$ given \kbd{gal=galoisinit(nf)}, and that $pr$ is 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 ramification group of $\goth{P}$. 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$. \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.5.5/src/functions/number_fields/bnrdisclist0000644000175000017500000000533311636712103020770 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.5.5/src/functions/number_fields/rnfkummer0000644000175000017500000000250211636712103020451 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.5.5/src/functions/number_fields/rnfbasis0000644000175000017500000000141211636712103020251 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.5.5/src/functions/number_fields/nfelttrace0000644000175000017500000000022611636712103020573 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.5.5/src/functions/number_fields/nffactor0000644000175000017500000000267312147140046020255 0ustar billbillFunction: nffactor Section: number_fields C-Name: nffactor Prototype: GG Help: nffactor(nf,x): factor polynomial x in number field nf. Doc: factorization of the univariate polynomial $x$ over the number field $\var{nf}$ given by \kbd{nfinit}. $x$ has coefficients in $\var{nf}$ (i.e.~either scalar, polmod, polynomial or column vector). The main variable of $\var{nf}$ must be of \emph{lower} priority than that of $x$ (see \secref{se:priority}). However if the polynomial defining the number field occurs explicitly in the coefficients of $x$ (as modulus of a \typ{POLMOD}), its main variable must be \emph{the same} as the main variable of $x$. 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\noindent 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: factors 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}. pari-2.5.5/src/functions/number_fields/rnfidealmul0000644000175000017500000000063211636712103020747 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.5.5/src/functions/number_fields/rnfisabelian0000644000175000017500000000067011636712103021104 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.5.5/src/functions/number_fields/nfbasis0000644000175000017500000000363612147140046020100 0ustar billbillFunction: nfbasis Section: number_fields C-Name: nfbasis0 Prototype: GD0,L,DG Help: nfbasis(x,{flag=0},{fa}): integral basis of the field Q[a], where a is a root of the polynomial x, using the round 4 algorithm. Second and third args are optional. Binary digits of flag mean 1: assume that no square of a prime>primelimit divides the discriminant of x, 2: use round 2 algorithm instead. If present, fa provides the matrix of a partial factorization of the discriminant of x, useful if one wants only an order maximal at certain primes only. Doc: \idx{integral basis} of the number field defined by the irreducible, preferably monic, polynomial $x$, using a modified version of the \idx{round 4} algorithm by default, due to David \idx{Ford}, Sebastian \idx{Pauli} and Xavier \idx{Roblot}. The binary digits of $\fl$ have the following meaning: 1: assume that no square of a prime greater than the default \kbd{primelimit} divides the discriminant of $x$, i.e.~that the index of $x$ has only small prime divisors. 2: use \idx{round 2} algorithm. For small degrees and coefficient size, this is sometimes a little faster. (This program is the translation into C of a program written by David \idx{Ford} in Algeb.) Thus for instance, if $\fl=3$, this uses the round 2 algorithm and outputs an order which will be maximal at all the small primes. If \var{fa} is present, we assume (without checking!) that it is the two-column matrix of the factorization of the discriminant of the polynomial $x$. Note that it does \emph{not} have to be a complete factorization. This is especially useful if only a local integral basis for some small set of places is desired: only factors with exponents greater or equal to 2 will be considered. Variant: An extended version is \fun{GEN}{nfbasis}{GEN x, GEN *d, long flag, GEN fa = NULL}, where \kbd{*d} receives the discriminant of the number field (\emph{not} of the polynomial $x$). pari-2.5.5/src/functions/number_fields/idealdiv0000644000175000017500000000173611636712103020234 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.5.5/src/functions/number_fields/bnfcompress0000644000175000017500000000340711636712103020771 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.5.5/src/functions/number_fields/dirzetak0000644000175000017500000000053211636712103020261 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.5.5/src/functions/number_fields/rnflllgram0000644000175000017500000000121011636712103020576 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.5.5/src/functions/number_fields/nfdisc0000644000175000017500000000152112147140046017710 0ustar billbillFunction: nfdisc Section: number_fields C-Name: nfdisc0 Prototype: GD0,L,DG Help: nfdisc(x,{flag=0},{fa}): discriminant of the number field defined by the polynomial x using round 4. Optional args flag and fa are as in nfbasis. Doc: \idx{field discriminant} of the number field defined by the integral, preferably monic, irreducible polynomial $x$. $\fl$ and $fa$ are exactly as in \kbd{nfbasis}. That is, $fa$ provides the matrix of a partial factorization of the discriminant of $x$, and binary digits of $\fl$ are as follows: 1: assume that no square of a prime greater than \kbd{primelimit} divides the discriminant. 2: use the round 2 algorithm, instead of the default \idx{round 4}. This should be slower except maybe for polynomials of small degree and coefficients. Variant: Also available is \fun{GEN}{nfdisc}{GEN x} ($\fl=0$). pari-2.5.5/src/functions/number_fields/idealfrobenius0000644000175000017500000000200011636712103021427 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.5.5/src/functions/number_fields/rnfdisc0000644000175000017500000000141311636712103020073 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.5.5/src/functions/number_fields/idealaddtoone0000644000175000017500000000154411636712103021244 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.5.5/src/functions/number_fields/rnfcharpoly0000644000175000017500000000110012147140046020762 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.5.5/src/functions/number_fields/poltschirnhaus0000644000175000017500000000072211636712103021513 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.5.5/src/functions/number_fields/polred0000644000175000017500000000361612147140046017736 0ustar billbillFunction: polred Section: number_fields C-Name: polred0 Prototype: GD0,L,DG Help: polred(x,{flag=0},{fa}): reduction of the polynomial x (gives minimal polynomials only). Second and third args are optional. The following binary digits of flag are significant 1: partial reduction, 2: gives also elements. fa, if present, contains the factorization matrix of the discriminant. Doc: finds polynomials with reasonably small coefficients defining subfields of the number field defined by $x$. One of the polynomials always defines $\Q$ (hence is equal to $x-1$), and another always defines the same number field as $x$ if $x$ is irreducible. All $x$ accepted by \tet{nfinit} are also allowed here (e.g. non-monic polynomials, \kbd{nf}, \kbd{bnf}, \kbd{[x,Z\_K\_basis]}). 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. 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\noindent If $fa$ is given, it is assumed that it is the two-column matrix of the factorization of the discriminant of the polynomial $x$. Variant: Also available is \fun{GEN}{polred}{GEN x} ($\fl = 0$). The function \kbd{polred0} is provided for backward compatibility; instead of the above hardcoded numerical flags (which happen to be inconsistent), one should use \fun{GEN}{Polred}{GEN x, long flag, GEN fa} where flag is an or-ed combination of \tet{nf_PARTIALFACT} (partial factorization of the discriminant) and \tet{nf_ORIG} (give also elements). pari-2.5.5/src/functions/number_fields/nffactorback0000644000175000017500000000146211636712103021072 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.5.5/src/functions/number_fields/rnfidealtwoelt0000644000175000017500000000071711636712103021474 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.5.5/src/functions/number_fields/nfroots0000644000175000017500000000261211636712103020137 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.5.5/src/functions/number_fields/nfeltpowmodpr0000644000175000017500000000100011636712103021333 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.5.5/src/functions/number_fields/idealappr0000644000175000017500000000241211636712103020404 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.5.5/src/functions/number_fields/nfinit0000644000175000017500000001622312147140046017736 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 In case \var{pol} has a huge discriminant which is difficult to factor, the special input format $[\var{pol},B]$ is also accepted where \var{pol} is a polynomial as above and $B$ is the integer basis, as would be computed by \tet{nfbasis}. This is useful if the integer basis is known in advance, or was computed conditionally. \bprog ? pol = polcompositum(x^5 - 101, polcyclo(7))[1]; ? B = nfbasis(pol, 1); \\ faster than nfbasis(pol), but conditional ? nf = nfinit( [pol, B] ); ? factor( abs(nf.disc) ) [5 18] [7 25] [101 24] @eprog \kbd{B} is conditional when its discriminant, which is \kbd{nf.disc}, can't be factored. In this example, the above factorization 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 \kbd{polred} 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$, does a \kbd{polred} 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 a \kbd{polred} reduction. 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}: slow down the routine by using an obsolete normalization algorithm (do not use this one!), \item \tet{nf_PARTIALFACT}: lazy factorization of the polynomial discriminant. Result is conditional unless the \emph{field} discriminant obtained is fully factored by \bprog Z_factor_limit(disc, 0) @eprog\noindent Namely the ``maximal order'' may not be maximal at any prime bigger than \kbd{primelimit} dividing the field discriminant. pari-2.5.5/src/functions/number_fields/nfdetint0000644000175000017500000000052611636712103020262 0ustar billbillFunction: nfdetint Section: number_fields C-Name: nfdetint Prototype: GG Help: nfdetint(nf,x): multiple of the ideal determinant of the pseudo generating set x. Doc: 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}. pari-2.5.5/src/functions/number_fields/bnrconductor0000644000175000017500000000202411636712103021144 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.5.5/src/functions/number_fields/bnfnarrow0000644000175000017500000000146311636712103020446 0ustar billbillFunction: bnfnarrow Section: number_fields C-Name: buchnarrow Prototype: G Help: bnfnarrow(bnf): given a big number field as output by bnfinit, gives as a 3-component vector the structure of the narrow class group. Doc: $\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}. pari-2.5.5/src/functions/number_fields/bnfisintnorm0000644000175000017500000000116512147140046021156 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}. pari-2.5.5/src/functions/number_fields/bnfsignunit0000644000175000017500000000167211636712103021000 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.5.5/src/functions/number_fields/rnfequation0000644000175000017500000000307111636712103021000 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 the absolute equation apol of the number field defined by pol. flag is optional, and can be 0: default, or non-zero, gives [apol,th], where th expresses the root of nf.pol in terms of the root of apol. 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 the absolute equation of $L$ over $\Q$. If $\fl$ is non-zero, outputs a 3-component row vector $[z,a,k]$, where $z$ is the absolute equation of $L$ over $\Q$, as in the default behavior, $a$ expresses as an element of $L$ a root $\alpha$ of the polynomial defining the base field $\var{nf}$, and $k$ is a small integer such that $\theta = \beta+k\alpha$ where $\theta$ is a root of $z$ and $\beta$ a root of $\var{pol}$. 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, an error message will be issued. 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.5.5/src/functions/number_fields/polgalois0000644000175000017500000001006112147140046020432 0ustar billbillFunction: polgalois Section: number_fields C-Name: polgalois Prototype: Gp Help: polgalois(x): Galois group of the polynomial x (see manual for group coding). Return [n, s, k, name] where n is the 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 $x\in\Q[X]$. In the present version \vers, $x$ must be irreducible and the degree of $x$ must be less than or equal to 7. On certain versions for which the data file of Galois resolvents has been installed (available in the Unix distribution as a separate package), degrees 8, 9, 10 and 11 are also implemented. 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_n$, $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 $n > 7$, $k$ is the numbering of the group among all transitive subgroups of $S_n$, 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 $n \leq 7$, it was ad hoc, so as to ensure that a given triple would design a unique group. Specifically, for polynomials of degree $\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.5.5/src/functions/number_fields/rnfinit0000644000175000017500000000643711636712103020127 0ustar billbillFunction: rnfinit Section: number_fields C-Name: rnfinit Prototype: GG Help: rnfinit(nf,pol): pol being a non constant 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 all the necessary 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}$, $m$ the degree of the base field, $n$ the relative degree, $L$ the large field (of relative degree $n$ or absolute degree $nm$), $r_1$ and $r_2$ the number of real and complex places of $K$. $\var{rnf}[1]$ contains the relative polynomial \var{pol}. $\var{rnf}[2]$ is currently unused. $\var{rnf}[3]$ 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]$ 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]$ is a two-component row vector, where the first component is the relative integral pseudo basis expressed as polynomials (in the variable of $pol$) with polmod coefficients in $\var{nf}$, and the second component 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]$ is $\var{nf}$. $\var{rnf}[11]$ is the output of \kbd{rnfequation(nf, pol, 1)}. Namely, a vector \var{vabs} with 3 entries describing the \emph{absolute} extension $L/\Q$. $\var{vabs}[1]$ is an absolute equation, more conveniently obtained as \kbd{rnf.pol}. $\var{vabs}[2]$ expresses the generator $\alpha$ of the number field $\var{nf}$ as a polynomial modulo the absolute equation $\var{vabs}[1]$. $\var{vabs}[3]$ is a small integer $k$ such that, if $\beta$ is an abstract root of \var{pol} and $\alpha$ the generator of $\var{nf}$, the generator whose root is \var{vabs} will be $\beta + k \alpha$. Note that one must be very careful if $k\neq0$ when dealing simultaneously with absolute and relative quantities since 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 strongly advise to change the relative polynomial so that its root will be $\beta + k \alpha$. Typically, the GP instruction would be \kbd{pol = subst(pol, x, x - k*Mod(y,\var{nf}.pol))} $\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.5.5/src/functions/number_fields/rnfeltup0000644000175000017500000000112211636712103020277 0ustar billbillFunction: rnfeltup Section: number_fields C-Name: rnfelementup 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$ expressed as a polynomial or polmod, computes $x$ as an element of the absolute extension $L/\Q$ as a polynomial modulo the absolute equation \kbd{\var{rnf}.pol}. If $x$ is given on the integral basis of $K$, apply \kbd{nfbasistoalg} first, otherwise PARI will believe you are dealing with a vector. pari-2.5.5/src/functions/number_fields/polcompositum0000644000175000017500000000560212147140046021360 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. Assuming $P$ is irreducible (of smaller degree than $Q$ for efficiency), it is in general \emph{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 quite often defined by a complicated polynomial, which it is advisable to reduce before further work. Here is a simple example involving the field $\Q(\zeta_5, 5^{1/5})$: \bprog ? z = polcompositum(x^5 - 5, polcyclo(5), 1)[1]; ? pol = z[1] \\@com \kbd{pol} defines the compositum %2 = 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 = z[2]; a^5 - 5 \\@com \kbd{a} is a fifth root of $5$ %3 = 0 ? z = polredabs(pol, 1); \\@com look for a simpler polynomial ? pol = z[1] %5 = x^20 + 25*x^10 + 5 ? a = subst(a.pol, x, z[2]) \\@com \kbd{a} in the new coordinates %6 = Mod(-5/22*x^19 + 1/22*x^14 - 123/22*x^9 + 9/11*x^4, x^20 + 25*x^10 + 5) @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.5.5/src/functions/number_fields/nfeltreducemodpr0000644000175000017500000000100711636712103022004 0ustar billbillFunction: nfeltreducemodpr Section: number_fields C-Name: nfreducemodpr Prototype: GGG Help: nfeltreducemodpr(nf,x,pr): element x modulo pr in nf, where pr is in modpr format (see nfmodprinit). Doc: 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}. 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.5.5/src/functions/number_fields/rnfsteinitz0000644000175000017500000000172511636712103021030 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.5.5/src/functions/number_fields/galoisidentify0000644000175000017500000000212111636712103021452 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.5.5/src/functions/number_fields/zetak0000644000175000017500000000376711636712103017577 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.5.5/src/functions/number_fields/rnfidealreltoabs0000644000175000017500000000124711636712103021770 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: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being a relative ideal, gives 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 following routine might be useful: \bprog \\ return y = rnfidealreltoabs(rnf,...) as an ideal in HNF form \\ associated to nf = nfinit( rnf.pol ); idealgentoHNF(nf, y) = mathnf( Mat( nfalgtobasis(nf, y) ) ); @eprog pari-2.5.5/src/functions/number_fields/bnrstark0000644000175000017500000000432011636712103020271 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.5.5/src/functions/number_fields/polredord0000644000175000017500000000102512147140046020433 0ustar billbillFunction: polredord Section: number_fields C-Name: ordred 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{polred(,1)} or \kbd{polredabs(,16)}. pari-2.5.5/src/functions/number_fields/nfeltdiv0000644000175000017500000000033711636712103020262 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.5.5/src/functions/number_fields/bnrinit0000644000175000017500000000360711636712103020117 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. 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. 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.5.5/src/functions/number_fields/rnfnormgroup0000644000175000017500000000211611636712103021202 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.5.5/src/functions/number_fields/nfeltpow0000644000175000017500000000054211636712103020303 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.5.5/src/functions/number_fields/rnfisnorm0000644000175000017500000000430711636712103020465 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.5.5/src/functions/number_fields/bnfsunit0000644000175000017500000000220211636712103020270 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.5.5/src/functions/number_fields/ideallist0000644000175000017500000000413011636712103020414 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.5.5/src/functions/number_fields/idealprimedec0000644000175000017500000000326011636712103021234 0ustar billbillFunction: idealprimedec Section: number_fields C-Name: idealprimedec Prototype: GG Help: idealprimedec(nf,p): prime ideal decomposition of the prime number p in the number field nf as a vector of 5 component vectors [p,a,e,f,b] 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. Doc: computes the prime ideal decomposition of the (positive) prime number $p$ in the number field $K$ represented by \var{nf}. If a non-prime $p$ is given the result is undefined. The result is a vector of \tev{prid} structures, each representing one of the prime ideals above $p$ in the number field $\var{nf}$. The representation $\kbd{pr}=[p,a,e,f,b]$ of a prime ideal means the following: $a$ and $b$ are algebraic integers in the maximal order $\Z_K$; the prime ideal is equal to $\goth{p} = p\Z_K + a\Z_K$; $e$ is the ramification index; $f$ is the residual index; and $b$ is such that $\goth{p}^{-1}=\Z_K+ b/ p\Z_K$, which is used internally to compute valuations. The algebraic number $a$ is guaranteed to have a valuation equal to 1 at the prime ideal (this is automatic if $e>1$). 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.5.5/src/functions/number_fields/galoisfixedfield0000644000175000017500000000357711636712103021762 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.5.5/src/functions/number_fields/bnfisnorm0000644000175000017500000000276112147140046020446 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.5.5/src/functions/number_fields/idealfactorback0000644000175000017500000000344711636712103021552 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.5.5/src/functions/number_fields/idealpow0000644000175000017500000000160411636712103020251 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.5.5/src/functions/number_fields/idealred0000644000175000017500000000553611636712103020226 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.5.5/src/functions/number_fields/rnfdet0000644000175000017500000000035311636712103017727 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.5.5/src/functions/number_fields/rnfeltreltoabs0000644000175000017500000000120211636712103021465 0ustar billbillFunction: rnfeltreltoabs Section: number_fields C-Name: rnfelementreltoabs 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}. If $x$ is given on the relative integral basis, apply \kbd{rnfbasistoalg} first, otherwise PARI will believe you are dealing with a vector. pari-2.5.5/src/functions/number_fields/galoisgetpol0000644000175000017500000000264411636712103021143 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 \kbd{pol} is the polynomial and \kbd{den} is the common denominator of the conjugates expressed as a polynomial in a root of \kbd{pol}, which can be passed as an optional argument to \tet{galoisinit} and \tet{nfgaloisconj} as follows: \bprog V=galoisgetpol(8,4,1); G=galoisinit(V[1], V[2]) \\ passing V[2] speeds up the computation @eprog If $b$ and $s$ are omitted, return the number of isomorphic class of groups of order $a$. Variant: Also available is \fun{GEN}{galoisnbpol}{long a} when $b$ and $s$ are omitted. pari-2.5.5/src/functions/number_fields/galoispermtopol0000644000175000017500000000154511636712103021671 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.5.5/src/functions/number_fields/idealadd0000644000175000017500000000246312147140046020177 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.5.5/src/functions/number_fields/rnfidealup0000644000175000017500000000121211706644717020606 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: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an ideal of $K$, gives 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 following routine might be useful: \bprog \\ return y = rnfidealup(rnf,...) as an ideal in HNF form \\ associated to nf = nfinit( rnf.pol ); idealgentoHNF(nf, y) = mathnf( Mat( matalgtobasis(nf, y) ) ); @eprog pari-2.5.5/src/functions/number_fields/idealintersect0000644000175000017500000000141112147140046021437 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 * vecextract(Ker, Str("..", #A), "..") ) } @eprog pari-2.5.5/src/functions/number_fields/galoissubcyclo0000644000175000017500000000501511636712103021467 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.5.5/src/functions/number_fields/nfisincl0000644000175000017500000000172411636712103020255 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.5.5/src/functions/number_fields/bnfissunit0000644000175000017500000000102211636712103020623 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.5.5/src/functions/number_fields/bnrconductorofchar0000644000175000017500000000066211636712103022335 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.5.5/src/functions/number_fields/bnrisconductor0000644000175000017500000000104511636712103021502 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.5.5/src/functions/number_fields/rnfpseudobasis0000644000175000017500000000153211636712103021474 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.5.5/src/functions/number_fields/rnfalgtobasis0000644000175000017500000000074111636712103021304 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.5.5/src/functions/number_fields/nfrootsof10000644000175000017500000000306311636712103020546 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.5.5/src/functions/number_fields/idealhnf0000644000175000017500000000300412147140046020212 0ustar billbillFunction: idealhnf Section: number_fields C-Name: idealhnf0 Prototype: GGDG Help: idealhnf(nf,a,{b}): hermite normal form of the ideal a in the number field nf. If called as idealhnf(nf,a,b), the ideal is given as aZ_K+bZ_K in the number field K defined by nf. Doc: gives the \idx{Hermite normal form} of the ideal $a\Z_K+b\Z_K$, where $a$ and $b$ 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 $a$: $a$ 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, $a$ is the $\Z_K$-module they generate, \item if $N$ or more are given, it is \emph{assumed} that they form a $\Z$-basis (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 Variant: Also available is \fun{GEN}{idealhnf}{GEN nf, GEN a}. pari-2.5.5/src/functions/number_fields/nfsubfields0000644000175000017500000000171411636712103020753 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.5.5/src/functions/number_fields/nfalgtobasis0000644000175000017500000000110411636712103021114 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.5.5/src/functions/number_fields/nfbasistoalg0000644000175000017500000000107111636712103021117 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.5.5/src/functions/number_fields/nfgaloisapply0000644000175000017500000000425411636712103021321 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 specificed 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.5.5/src/functions/number_fields/matbasistoalg0000644000175000017500000000051211636712103021274 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.5.5/src/functions/number_fields/nffactormod0000644000175000017500000000165211636712103020752 0ustar billbillFunction: nffactormod Section: number_fields C-Name: nffactormod Prototype: GGG Help: nffactormod(nf,pol,pr): factorize polynomial pol modulo prime ideal pr in number field nf. Doc: factorization of the univariate polynomial $x$ modulo the prime ideal \var{pr} in the number field $\var{nf}$. $x$ can have coefficients in the number field (scalar, polmod, polynomial, column vector) or modulo the prime ideal (intmod modulo the rational prime under \var{pr}, polmod or polynomial with intmod coefficients, column vector of intmod). The prime ideal \var{pr} \emph{must} be in the format output by \kbd{idealprimedec}. 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}). pari-2.5.5/src/functions/number_fields/bnrisprincipal0000644000175000017500000000243211636712103021464 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.5.5/src/functions/number_fields/idealfactor0000644000175000017500000000070611636712103020724 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.5.5/src/functions/number_fields/rnfidealhnf0000644000175000017500000000073311636712103020727 0ustar billbillFunction: rnfidealhnf Section: number_fields C-Name: rnfidealhermite 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.5.5/src/functions/number_fields/nfisisom0000644000175000017500000000042411636712103020273 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.5.5/src/functions/number_fields/rnfidealnormrel0000644000175000017500000000065411636712103021634 0ustar billbillFunction: rnfidealnormrel Section: number_fields C-Name: rnfidealnormrel Prototype: GG Help: rnfidealnormrel(rnf,x): relative norm of the ideal x. 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 relative norm of $x$ as a ideal of $K$ in HNF. pari-2.5.5/src/functions/number_fields/rnfeltabstorel0000644000175000017500000000074511636712103021500 0ustar billbillFunction: rnfeltabstorel Section: number_fields C-Name: rnfelementabstorel 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. pari-2.5.5/src/functions/number_fields/modreverse0000644000175000017500000000263312147140046020622 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) *** at top-level: modreverse(u) *** ^------------- *** modreverse: reverse polmod does not exist: Mod(-x^3+9*x, x^4-10*x^2+1). ? minpoly(u) %6 = x^2 - 8 @eprog pari-2.5.5/src/functions/number_fields/idealinv0000644000175000017500000000063611636712103020244 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.5.5/src/functions/number_fields/nfeltadd0000644000175000017500000000033311636712103020224 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.5.5/src/functions/number_fields/rnfpolredabs0000644000175000017500000000266212147140046021132 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: 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 1: returns $[P,a]$ where $P$ is the default output and $a$ is an element expressed on a root of $P$ whose characteristic polynomial is \var{pol} 2: returns an absolute polynomial (same as {\tt rnfequation(\var{nf},rnfpolredabs(\var{nf},\var{pol}))} but faster). 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{Remark} In the present implementation, this is both faster and much more efficient than \kbd{rnfpolred}, the difference being more dramatic than in the absolute case. This is because the implementation of \kbd{rnfpolred} is based on (a partial implementation of) an incomplete reduction theory of lattices over number fields, the function \kbd{rnflllgram}, which deserves to be improved. pari-2.5.5/src/functions/number_fields/idealtwoelt0000644000175000017500000000214311636712103020761 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 explicit approximation theorem. $x$ is an ideal in any form (possibly an extended ideal, whose principal part is ignored) and the result is a row vector $[a,\alpha]$ with two components such that $x=a\Z_K+\alpha\Z_K$ and $a\in\Z$, where $a$ is the one passed as argument if any. Unless $x$ was given as a principal ideal, $a$ is chosen to be the positive generator of $x\cap\Z$. Note that when an explicit $a$ is given, we must factor it and this may be costly. When $a$ is omitted, we use a fast lazy factorization of $x\cap \Z$, yielding an algorithm in randomized polynomial time (and generally much faster in practice). Variant: Also available are \fun{GEN}{idealtwoelt}{GEN nf, GEN x} and \fun{GEN}{idealtwoelt2}{GEN nf, GEN x, GEN a}. pari-2.5.5/src/functions/number_fields/nfhilbert0000644000175000017500000000134011636712103020417 0ustar billbillFunction: nfhilbert Section: number_fields C-Name: nfhilbert0 Prototype: lGGGDG Help: 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. Doc: 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}. Variant: Also available is \fun{long}{nfhilbert}{GEN bnf,GEN a,GEN b} (global quadratic Hilbert symbol). pari-2.5.5/src/functions/number_fields/galoisisnormal0000644000175000017500000000105711636712103021472 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.5.5/src/functions/number_fields/nfhnf0000644000175000017500000000077311636712103017552 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.5.5/src/functions/number_fields/nfgaloisconj0000644000175000017500000000507711636712103021131 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.5.5/src/functions/number_fields/rnfbasistoalg0000644000175000017500000000064611636712103021310 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.5.5/src/functions/number_fields/ideallog0000644000175000017500000000205211636712103020223 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 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.5.5/src/functions/number_fields/bnfdecodemodule0000644000175000017500000000046312147140046021565 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. pari-2.5.5/src/functions/number_fields/rnfeltdown0000644000175000017500000000114311636712103020625 0ustar billbillFunction: rnfeltdown Section: number_fields C-Name: rnfelementdown 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 an error will occur). If $x$ is given on the relative integral basis, apply \kbd{rnfbasistoalg} first, otherwise PARI will believe you are dealing with a vector. pari-2.5.5/src/functions/number_fields/nfeltdivmodpr0000644000175000017500000000101411636712103021315 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.5.5/src/functions/number_fields/rnfidealnormabs0000644000175000017500000000103511636712103021611 0ustar billbillFunction: rnfidealnormabs Section: number_fields C-Name: rnfidealnormabs Prototype: GG Help: rnfidealnormabs(rnf,x): absolute norm of the ideal x. 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 norm of the ideal $x$ considered as an ideal of the absolute extension $L/\Q$. This is identical to \kbd{idealnorm(rnfidealnormrel(\var{rnf},x))}, but faster. pari-2.5.5/src/functions/number_fields/bnfisprincipal0000644000175000017500000000527511636712103021460 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.5.5/src/functions/number_fields/rnfpolred0000644000175000017500000000102711636712103020437 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: 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{rnfpolredabs}. pari-2.5.5/src/functions/number_fields/zetakinit0000644000175000017500000000215712147140046020452 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. pari-2.5.5/src/functions/number_fields/rnfhnfbasis0000644000175000017500000000106211636712103020746 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.5.5/src/functions/number_fields/rnfidealdown0000644000175000017500000000072411636712103021123 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}), returns the ideal of $K$ below $x$, i.e.~the intersection of $x$ with $K$. pari-2.5.5/src/functions/number_fields/nfkermodpr0000644000175000017500000000070011636712103020610 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.5.5/src/functions/number_fields/rnfisfree0000644000175000017500000000077711636712103020442 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.5.5/src/functions/number_fields/newtonpoly0000644000175000017500000000120511636712103020660 0ustar billbillFunction: newtonpoly Section: number_fields C-Name: newtonpoly Prototype: GG Help: newtonpoly(x,p): Newton polygon of polynomial x with respect to the prime p. Doc: 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}. pari-2.5.5/src/functions/number_fields/rnfidealabstorel0000644000175000017500000000130011636712103021756 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$ 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$. If $x$ is an ideal in HNF form, associated to an \var{nf} structure, for instance as output by $\tet{idealhnf}(\var{nf},\dots)$, use \kbd{rnfidealabstorel(rnf, nf.zk * x)} to convert it to a relative ideal. pari-2.5.5/src/functions/number_fields/nfeltmulmodpr0000644000175000017500000000101111636712103021325 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.5.5/src/functions/number_fields/factornf0000644000175000017500000000245111636712103020250 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.5.5/src/functions/number_fields/nfeltval0000644000175000017500000000077311636712103020266 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 their the valuation at \var{pr} of the element $x$. The same result could be obtained using \kbd{idealval(\var{nf},x,\var{pr})} (since $x$ would then be converted to a principal ideal), but it would be less efficient. pari-2.5.5/src/functions/number_fields/bnrrootnumber0000644000175000017500000000266511636712103021353 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.5.5/src/functions/number_fields/galoissubgroups0000644000175000017500000000145211636712103021676 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.5.5/src/functions/number_fields/nfhnfmod0000644000175000017500000000103311636712103020240 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.5.5/src/functions/number_fields/nfeltmod0000644000175000017500000000064711636712103020263 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.5.5/src/functions/number_fields/bnrclassno0000644000175000017500000000132111636712103020605 0ustar billbillFunction: bnrclassno Section: number_fields C-Name: bnrclassno Prototype: GG Help: bnrclassno(bnf,I): ray class number of the module I for the big number field bnf. Faster than bnrinit if only the ray class number is wanted. Doc: $\var{bnf}$ being as output by \kbd{bnfinit} (units are mandatory unless the ideal is trivial), and $I$ being a modulus, computes the ray class number of the number field for the modulus $I$. One can input the associated \var{bid} for $I$ 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. pari-2.5.5/src/functions/number_fields/nfeltreduce0000644000175000017500000000054711636712103020752 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.5.5/src/functions/number_fields/galoissubfields0000644000175000017500000000066011636712103021625 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.5.5/src/functions/number_fields/ideallistarch0000644000175000017500000000332211636712103021254 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.5.5/src/functions/number_fields/galoisinit0000644000175000017500000000744112147140046020613 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 neccessary informations 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 $i=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.5.5/src/functions/number_fields/idealmin0000644000175000017500000000060111636712103020223 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.5.5/src/functions/number_fields/idealcoprime0000644000175000017500000000057011636712103021103 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.5.5/src/functions/number_fields/rnfisnorminit0000644000175000017500000000204411636712103021345 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.5.5/src/functions/number_fields/nfnewprec0000644000175000017500000000114411636712103020433 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.5.5/src/functions/number_fields/idealval0000644000175000017500000000052211636712103020224 0ustar billbillFunction: idealval Section: number_fields C-Name: idealval Prototype: lGGG Help: idealval(nf,x,pr): valuation at pr given in idealprimedec format of the ideal x in the number field nf. Doc: gives the valuation of the ideal $x$ at the prime ideal \var{pr} in the number field $\var{nf}$, where \var{pr} is in \kbd{idealprimedec} format. pari-2.5.5/src/functions/number_fields/bnrdisc0000644000175000017500000000266011636712103020074 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.5.5/src/functions/number_fields/bnrclassnolist0000644000175000017500000000224012147140046021501 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.5.5/src/functions/number_fields/nfsnf0000644000175000017500000000223511636712103017560 0ustar billbillFunction: nfsnf Section: number_fields C-Name: nfsnf Prototype: GG Help: nfsnf(nf,x): if x=[A,I,J], outputs [c_1,...c_n] Smith normal form of x. Doc: given a $\Z_K$-module $x$ associated to the integral pseudo-matrix $(A,I,J)$, returns an ideal list $d_1,\dots,d_n$ which is the \idx{Smith normal form} of $x$. In other words, $x$ is isomorphic to $\Z_K/d_1\oplus\cdots\oplus\Z_K/d_n$ and $d_i$ divides $d_{i-1}$ for $i\ge2$. 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$. pari-2.5.5/src/functions/gp2c/0000755000175000017500000000000012212611624014533 5ustar billbillpari-2.5.5/src/functions/gp2c/clone0000644000175000017500000000061111636712103015557 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) (gen):gen gclone($1) pari-2.5.5/src/functions/gp2c/copy0000644000175000017500000000060111636712103015430 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.5.5/src/functions/gp2c/unclone0000644000175000017500000000015411636712103016124 0ustar billbillFunction: unclone Class: gp2c Description: (small):void (void)0 /*unclone*/ (gen):void gunclone($1) pari-2.5.5/src/functions/graphic/0000755000175000017500000000000012212611624015315 5ustar billbillpari-2.5.5/src/functions/graphic/plot0000644000175000017500000000112011636712103016213 0ustar billbillFunction: plot Class: highlevel Section: graphic C-Name: plot Prototype: vV=GGEDGDGp Help: 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 minima (resp. the maxima) of the expression is used instead. Doc: 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 minima (resp. the maxima) of the computed values of the expression is used instead. pari-2.5.5/src/functions/graphic/plotrecthraw0000644000175000017500000000166411636712103017770 0ustar billbillFunction: plotrecthraw Class: highlevel Section: graphic C-Name: rectplothraw Prototype: LGD0,L, Help: 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. Doc: 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. pari-2.5.5/src/functions/graphic/plotrpoint0000644000175000017500000000066211636712103017461 0ustar billbillFunction: plotrpoint Class: highlevel Section: graphic C-Name: rectrpoint Prototype: vLGG Help: plotrpoint(w,dx,dy): draw a point (and move cursor) at position dx,dy relative to present position of the cursor in rectwindow w. Doc: 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)$. pari-2.5.5/src/functions/graphic/plotrbox0000644000175000017500000000101711636712103017113 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.5.5/src/functions/graphic/plotbox0000644000175000017500000000102311636712103016726 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.5.5/src/functions/graphic/plotcursor0000644000175000017500000000042411636712103017457 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.5.5/src/functions/graphic/plotstring0000644000175000017500000000163011636712103017450 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.5.5/src/functions/graphic/plotpointtype0000644000175000017500000000105111636712103020172 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.5.5/src/functions/graphic/plothsizes0000644000175000017500000000137311636712103017453 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.5.5/src/functions/graphic/plotlinetype0000644000175000017500000000107611636712103017777 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.5.5/src/functions/graphic/plotcopy0000644000175000017500000000156311636712103017121 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.5.5/src/functions/graphic/plotmove0000644000175000017500000000034211636712103017107 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.5.5/src/functions/graphic/psdraw0000644000175000017500000000104311636712103016541 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.5.5/src/functions/graphic/plotclip0000644000175000017500000000070311636712103017071 0ustar billbillFunction: plotclip Class: highlevel Section: graphic C-Name: rectclip Prototype: vL Help: plotclip(w): clip the contents of the rectwindow to the bounding box (except strings). Doc: `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. pari-2.5.5/src/functions/graphic/plotcolor0000644000175000017500000000116711636712103017265 0ustar billbillFunction: plotcolor Class: highlevel Section: graphic C-Name: rectcolor Prototype: vLL Help: 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. Doc: 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. pari-2.5.5/src/functions/graphic/plotpoints0000644000175000017500000000162011636712103017455 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.5.5/src/functions/graphic/psplothraw0000644000175000017500000000052411636712103017447 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.5.5/src/functions/graphic/plotinit0000644000175000017500000000237311636712103017112 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.5.5/src/functions/graphic/psploth0000644000175000017500000000052411636712103016735 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.5.5/src/functions/graphic/plotdraw0000644000175000017500000000160011636712103017074 0ustar billbillFunction: plotdraw Class: highlevel Section: graphic C-Name: rectdraw_flag Prototype: vGD0,L, Help: 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. Doc: 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 pari-2.5.5/src/functions/graphic/plothraw0000644000175000017500000000136611636712103017111 0ustar billbillFunction: plothraw Class: highlevel Section: graphic C-Name: plothraw Prototype: GGD0,L, Help: 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(). Doc: 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}. pari-2.5.5/src/functions/graphic/plotkill0000644000175000017500000000065611636712103017104 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.5.5/src/functions/graphic/plotrecth0000644000175000017500000000110111636712103017240 0ustar billbillFunction: plotrecth Class: highlevel Section: graphic C-Name: rectploth Prototype: 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 Help: 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. Doc: 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. pari-2.5.5/src/functions/graphic/ploth0000644000175000017500000001220312147140046016366 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 points 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 15 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.5.5/src/functions/graphic/plotpointsize0000644000175000017500000000055411636712103020172 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.5.5/src/functions/graphic/plotrline0000644000175000017500000000073711636712103017262 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.5.5/src/functions/graphic/plotlines0000644000175000017500000000234111636712103017254 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.5.5/src/functions/graphic/plotrmove0000644000175000017500000000061611636712103017275 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.5.5/src/functions/graphic/plotscale0000644000175000017500000000134711636712103017236 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 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. If $\fl=-1$, uses a variant of the \idx{LLL} algorithm due to Hastad, Lagarias and Schnorr (STACS 1986). If the precision is too low, the routine may enter an infinite loop. Faster than the alternatives if it converges, especially when the accuracy is much larger than what is really necessary; usually diverges, though. If $\fl=-2$, $x$ is allowed to be (and in any case interpreted as) a matrix. Returns a non trivial element of the kernel of $x$, or $0$ if $x$ has trivial kernel. The element is defined over the field of coefficients of $x$, and is in general not integral. If $\fl=-3$, uses the PSLQ algorithm. This may return a real number $B$, indicating that the input accuracy was exhausted and that no relation exist whose sup norm is less than $B$. If $\fl=-4$, uses an experimental 2-level PSLQ, which does not work at all. Don't use it! Variant: Also available are \fun{GEN}{lindep}{GEN x} ($\fl=0$) \fun{GEN}{lindep2}{GEN x, long bit} ($\fl\geq 0$, bypasses the check for $p$-adic inputs) and \fun{GEN}{deplin}{GEN x} ($\fl=-2$). pari-2.5.5/src/functions/linear_algebra/setsearch0000644000175000017500000000271712147140046020544 0ustar billbillFunction: setsearch Section: linear_algebra C-Name: setsearch Prototype: lGGD0,L, Help: setsearch(S,x,{flag=0}): looks if x belongs to the set S. If flag is 0 or omitted, returns 0 if it is 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: searches if $x$ belongs to the set $S$ (see \kbd{setisset}). A set is a vector of \typ{STR}, but this function works also if $S$ is a arbitrary \emph{sorted} vector or list (see \kbd{listsort}): if $x$ is not a \typ{STR}, we first replace it by \kbd{Str}$(x)$ \emph{unless} the first element of $S$ is also not a \typ{STR}. If $x$ belongs to the set and $\fl$ is zero or omitted, returns the index $j$ such that $S[j]=x$, otherwise returns 0. If $\fl$ is non-zero returns the index $j$ where $x$ should be inserted, and $0$ if it already belongs to $S$ (this is meant to be used in conjunction with \kbd{listinsert}, see below). \bprog ? T = [2,3,5,7]; S = Set(T); ? setsearch(S, 2) \\ search in a true set, t_INT 2 converted to string %2 = 1 ? setsearch(S, Str(2)) \\ search in a true set, no need for conversion %3 = 1 ? setsearch(T, 2) \\ search in a sorted vector, no need for conversion %4 = 1 ? setsearch(T, Str(2)) \\ search in a sorted vector, t_STR "2" not found %5 = 0 ? setsearch(S, 4) \\ not found %6 = 0 ? setsearch(S, 4, 1) \\ should have been inserted at index 3 %7 = 3 @eprog pari-2.5.5/src/functions/linear_algebra/matdetint0000644000175000017500000000174412147140046020553 0ustar billbillFunction: matdetint Section: linear_algebra C-Name: detint Prototype: G Help: matdetint(x): some multiple of the determinant of the lattice generated by the columns of x (0 if not of maximal rank). Useful with mathnfmod. Doc: $x$ being an $m\times n$ matrix with integer coefficients, this function computes a non-zero \emph{multiple} of the determinant of the lattice generated by the columns of $x$ if it has maximal rank $m$, and returns zero otherwise, using the Gauss-Bareiss algorithm. When $x$ is square, the exact determinant is obtained. 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 the exact determinant using \bprog matdet( mathnfmod(x, matdetint(x)) ) @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(x, 1)} or \kbd{mathnf(x, 4)} directly. pari-2.5.5/src/functions/linear_algebra/matsolve0000644000175000017500000000052312147140046020406 0ustar billbillFunction: matsolve Section: linear_algebra C-Name: gauss Prototype: GG Help: matsolve(M,B): Gaussian solution of MX=B (M matrix, B column vector). Doc: $M$ being an invertible matrix and $B$ a column vector, finds the solution $X$ of $MX=B$, using Gaussian elimination. This has the same effect as, but is a bit faster, than $M^{-1}*B$. pari-2.5.5/src/functions/linear_algebra/setunion0000644000175000017500000000071512147140046020423 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}). The function also works if both $x$ and $y$ are vectors of strictly increasing entries, according to \kbd{<}); in that case we return a vector of strictly increasing entries, not a set. Otherwise, the result is undefined. pari-2.5.5/src/functions/linear_algebra/concat0000644000175000017500000000371012147140046020024 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, it is easy to concatenate them vertically. To concatenate vectors sideways (i.e.~to obtain a two-row or two-column matrix), use \tet{Mat} instead (see the example there). 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 definitely \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.5.5/src/functions/linear_algebra/qflllgram0000644000175000017500000000344111636712103020540 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.5.5/src/functions/linear_algebra/vecsort0000644000175000017500000001033112147140046020237 0ustar billbillFunction: vecsort Section: linear_algebra C-Name: vecsort0 Prototype: GDGD0,L, Help: vecsort(x,{cmp},{flag=0}): sorts the vector of vectors (or matrix) x in ascending order, according to the comparison function cmp, if not omitted. (If cmp 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{cmp} is omitted, we use the standard comparison function \kbd{<}, thereby restricting the possible types for the elements of $x$ (integers, fractions or reals). If \kbd{cmp} 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{cmp}=\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],lex) \\ sort columns according to lex order %1 = [2 3] [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 ? cmp(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], cmp) @eprog\noindent The last example used the named \kbd{cmp} 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 2: sorts $x$ by ascending lexicographic order (as per the \kbd{lex} comparison function). \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.5.5/src/functions/linear_algebra/vector0000644000175000017500000000154511636712103020064 0ustar billbillFunction: vector Section: linear_algebra C-Name: vecteur Prototype: GDVDE Help: vector(n,{X},{expr=0}): row vector with n components of expression expr (X ranges from 1 to n). By default, fill with 0s. Doc: 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. Avoid modifying $X$ within \var{expr}; if you do, the formal variable still runs from $1$ to $n$. In particular, \kbd{vector(n,i,expr)} is not equivalent to \bprog v = vector(n) for (i = 1, n, v[i] = expr) @eprog\noindent 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} pari-2.5.5/src/functions/linear_algebra/vectorv0000644000175000017500000000044011636712103020243 0ustar billbillFunction: vectorv Section: linear_algebra C-Name: vvecteur Prototype: GDVDE Help: vectorv(n,{X},{expr=0}): column vector with n components of expression expr (X ranges from 1 to n). By default, fill with 0s. Doc: as \tet{vector}, but returns a column vector (type \typ{COL}). %\syn{NO} pari-2.5.5/src/functions/linear_algebra/matkerint0000644000175000017500000000154411636712103020557 0ustar billbillFunction: matkerint Section: linear_algebra C-Name: matkerint0 Prototype: GD0,L, Help: matkerint(x,{flag=0}): LLL-reduced Z-basis of the kernel of the matrix x with integral entries. flag is optional, and may be set to 0: default, uses LLL, 1: uses matrixqz (much slower). Doc: gives an \idx{LLL}-reduced $\Z$-basis for the lattice equal to the kernel of the matrix $x$ as columns of the matrix $x$ with integer entries (rational entries are not permitted). 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. Variant: See also \fun{GEN}{kerint}{GEN x} ($\fl=0$), which is a trivial wrapper around \bprog ZM_lll(ZM_lll(x, 0.99, LLL_KER), 0.99, LLL_INPLACE); @eprog\noindent Remove the outermost \kbd{ZM\_lll} if LLL-reduction is not desired (saves time). pari-2.5.5/src/functions/linear_algebra/matsolvemod0000644000175000017500000000264211636712103021113 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.5.5/src/functions/linear_algebra/qfsign0000644000175000017500000000055011636712103020044 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.5.5/src/functions/linear_algebra/matintersect0000644000175000017500000000121011636712103021251 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.5.5/src/functions/linear_algebra/matinverseimage0000644000175000017500000000146411636712103021742 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.5.5/src/functions/linear_algebra/setintersect0000644000175000017500000000075312147140046021275 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}). The function also works if both $x$ and $y$ are vectors of strictly increasing entries, according to \kbd{<}); in that case we return a vector of strictly increasing entries, not a set. Otherwise, the result is undefined. pari-2.5.5/src/functions/linear_algebra/matimagecompl0000644000175000017500000000071012147140046021371 0ustar billbillFunction: matimagecompl Section: linear_algebra C-Name: imagecompl Prototype: G 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}. 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.5.5/src/functions/linear_algebra/qfminim0000644000175000017500000001234412147140046020220 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 the first vector whose norm is less than $b$. In this variant, an explicit $b$ must be provided. 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$). pari-2.5.5/src/functions/linear_algebra/mathnfmod0000644000175000017500000000143211636712103020532 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.5.5/src/functions/linear_algebra/mathilbert0000644000175000017500000000040711636712103020711 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.5.5/src/functions/linear_algebra/matrixqz0000644000175000017500000000300012147140046020424 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( vecextract(x, Str("^",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.5.5/src/functions/linear_algebra/matrix0000644000175000017500000000115511636712103020063 0ustar billbillFunction: matrix Section: linear_algebra C-Name: matrice Prototype: GGDVDVDE Help: 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. Doc: 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} pari-2.5.5/src/functions/linear_algebra/mathnf0000644000175000017500000000470712147140046020041 0ustar billbillFunction: mathnf Section: linear_algebra C-Name: mathnf0 Prototype: GD0,L, Help: mathnf(x,{flag=0}): (upper triangular) Hermite normal form of x, basis for the lattice formed by the columns of x. flag is optional whose value range from 0 to 4 (0 if omitted), meaning : 0: naive algorithm. 1: as 0, but output 2-component vector [H,U] such that H is the HNF of x, and U is a unimodular matrix such that XU=H. 3: Batut's algorithm: output [H,U,P] where P is a permutation matrix such that P x U = H. 4: as 1, using a heuristic variant of LLL reduction along the way. Doc: if $x$ is a (not necessarily square) matrix with integer entries, 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$. If $\fl=0$, uses the naive algorithm. This is in general fastest but may require too much memory as the dimension gets large (bigger than 100, say), in which case you may try \kbd{mathnfmod(x, matdetint(x))} when $x$ has maximal rank, and \kbd{mathnf(x, 4)} otherwise. If $\fl=1$, outputs a two-component row vector $[H,U]$, where $H$ is the Hermite normal form of $x$ defined as above, and $U$ is the unimodular transformation matrix such that $xU=[0|H]$. When the kernel is large, $U$ has in general huge coefficients. In the worst case, the running time is exponential with respect to the dimension, but the routine behaves well in small dimension (less than 50 or 100, say). If $\fl=3$, 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 $xU$ gives $H$. This is in general slower than $\fl=1$ but the matrix $U$ is smaller; it may still be large. If $\fl=4$, as in case 1 above, but uses a variant of \idx{LLL} reduction along the way. The matrix $U$ is in general close to optimal (in terms of smallest $L_2$ norm), but the reduction is in general slow, although provably polynomial-time. Variant: Also available are \fun{GEN}{hnf}{GEN x} ($\fl=0$) and \fun{GEN}{hnfall}{GEN x} ($\fl=1$). To reduce \emph{huge} (say $400 \times 400$ and more) relation matrices (sparse with small entries), 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/alglin1.c}. pari-2.5.5/src/functions/linear_algebra/mathnfmodid0000644000175000017500000000053711636712103021054 0ustar billbillFunction: mathnfmodid Section: linear_algebra C-Name: hnfmodid Prototype: GG Help: mathnfmodid(x,d): (upper triangular) Hermite normal form of x concatenated with d times the identity matrix. Doc: outputs the (upper triangular) \idx{Hermite normal form} of $x$ concatenated with $d$ times the identity matrix. Assumes that $x$ has integer entries. pari-2.5.5/src/functions/linear_algebra/minpoly0000644000175000017500000000046512147140046020250 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.5.5/src/functions/linear_algebra/matpascal0000644000175000017500000000070411636712103020523 0ustar billbillFunction: matpascal Section: linear_algebra C-Name: matqpascal Prototype: LDG Help: matpascal(n,{q}): Pascal triangle of order n if q is omited. 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.5.5/src/functions/transcendental/0000755000175000017500000000000012212611624016705 5ustar billbillpari-2.5.5/src/functions/transcendental/Pi0000644000175000017500000000031712147140046017203 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$). pari-2.5.5/src/functions/transcendental/tan0000644000175000017500000000016211636712103017414 0ustar billbillFunction: tan Section: transcendental C-Name: gtan Prototype: Gp Help: tan(x): tangent of x. Doc: tangent of $x$. pari-2.5.5/src/functions/transcendental/besseli0000644000175000017500000000055411636712103020265 0ustar billbillFunction: besseli Section: transcendental C-Name: ibessel Prototype: GGp Help: besseli(nu,x): I-bessel function of index nu and argument x. Doc: $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). pari-2.5.5/src/functions/transcendental/cotan0000644000175000017500000000017411636712103017741 0ustar billbillFunction: cotan Section: transcendental C-Name: gcotan Prototype: Gp Help: cotan(x): cotangent of x. Doc: cotangent of $x$. pari-2.5.5/src/functions/transcendental/bernfrac0000644000175000017500000000046711636712103020424 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.5.5/src/functions/transcendental/arg0000644000175000017500000000030611636712103017403 0ustar billbillFunction: arg Section: transcendental C-Name: garg Prototype: Gp Help: arg(x): argument of x,such that -pi 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.5.5/src/functions/transcendental/teichmuller0000644000175000017500000000042611636712103021152 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.5.5/src/functions/transcendental/besselh20000644000175000017500000000032011636712103020335 0ustar billbillFunction: besselh2 Section: transcendental C-Name: hbessel2 Prototype: GGp Help: besselh2(nu,x): H^2-bessel function of index nu and argument x. Doc: $H^2$-Bessel function of index \var{nu} and argument $x$. pari-2.5.5/src/functions/transcendental/abs0000644000175000017500000000151111636712103017376 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.5.5/src/functions/transcendental/hyperu0000644000175000017500000000046211636712103020151 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.5.5/src/functions/transcendental/bernreal0000644000175000017500000000046011636712103020425 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.5.5/src/functions/transcendental/gammah0000644000175000017500000000025111636712103020063 0ustar billbillFunction: gammah Section: transcendental C-Name: ggamd Prototype: Gp Help: gammah(x): gamma of x+1/2 (x integer). Doc: gamma function evaluated at the argument $x+1/2$. pari-2.5.5/src/functions/transcendental/asin0000644000175000017500000000074411636712103017572 0ustar billbillFunction: asin Section: transcendental C-Name: gasin Prototype: Gp Help: asin(x): arc sine of x. Doc: 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)$. pari-2.5.5/src/functions/transcendental/acosh0000644000175000017500000000056011636712103017731 0ustar billbillFunction: acosh Section: transcendental C-Name: gach 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.5.5/src/functions/transcendental/gamma0000644000175000017500000000145011636712103017715 0ustar billbillFunction: gamma Section: transcendental C-Name: ggamma Prototype: Gp Help: gamma(s): gamma function at x, s a complex or p-adic number. 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 $p$-adic number, 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_{j1$ then $\text{atanh}(x)$ is complex. pari-2.5.5/src/functions/transcendental/incgam0000644000175000017500000000106712147140046020074 0ustar billbillFunction: incgam Section: transcendental C-Name: incgam0 Prototype: GGDGp Help: incgam(s,x,{y}): incomplete gamma function. y is optional and is the precomputed value of gamma(s). Doc: incomplete gamma function. The argument $x$ and $s$ are complex numbers ($x$ must be a positive real number if $s = 0$). The result returned is $\int_x^\infty e^{-t}t^{s-1}\,dt$. When $y$ is given, assume (of course without checking!) that $y=\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.5.5/src/functions/transcendental/tanh0000644000175000017500000000021111636712103017557 0ustar billbillFunction: tanh Section: transcendental C-Name: gth Prototype: Gp Help: tanh(x): hyperbolic tangent of x. Doc: hyperbolic tangent of $x$. pari-2.5.5/src/functions/transcendental/sin0000644000175000017500000000015411636712103017424 0ustar billbillFunction: sin Section: transcendental C-Name: gsin Prototype: Gp Help: sin(x): sine of x. Doc: sine of $x$. pari-2.5.5/src/functions/transcendental/polylog0000644000175000017500000000310011636712103020312 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.5.5/src/functions/transcendental/dilog0000644000175000017500000000035011636712103017727 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.5.5/src/functions/transcendental/erfc0000644000175000017500000000034212147140046017550 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$ ($x\in\R$). pari-2.5.5/src/functions/transcendental/eta0000644000175000017500000000212211636712103017401 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.5.5/src/functions/transcendental/Euler0000644000175000017500000000061412147140046017707 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 special reserved names which cannot be used for variables (the others are \kbd{I} and \kbd{Pi}, as well as all function names). pari-2.5.5/src/functions/transcendental/cosh0000644000175000017500000000020711636712103017566 0ustar billbillFunction: cosh Section: transcendental C-Name: gch Prototype: Gp Help: cosh(x): hyperbolic cosine of x. Doc: hyperbolic cosine of $x$. pari-2.5.5/src/functions/transcendental/weber0000644000175000017500000000205011636712103017734 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.5.5/src/functions/transcendental/besselj0000644000175000017500000000055411636712103020266 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.5.5/src/functions/transcendental/I0000644000175000017500000000021711636712103017023 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.5.5/src/functions/transcendental/sqr0000644000175000017500000000170311636712103017441 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.5.5/src/functions/transcendental/asinh0000644000175000017500000000055411636712103017741 0ustar billbillFunction: asinh Section: transcendental C-Name: gash 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.5.5/src/functions/transcendental/besselk0000644000175000017500000000031111636712103020256 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.5.5/src/functions/transcendental/sqrt0000644000175000017500000000145512147140046017630 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$ and $p$-adics are allowed as arguments. In that case, the square root (if it exists) which is returned is the one whose first $p$-adic digit is in the interval $[0,p/2]$. When the argument is an intmod a non-prime (or a non-prime-adic), the result is undefined. Variant: For a \typ{PADIC} $x$, the function \fun{GEN}{Qp_sqrt}{GEN x} is also available. pari-2.5.5/src/functions/transcendental/sqrtn0000644000175000017500000000275712147140046020014 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.5.5/src/functions/transcendental/eint10000644000175000017500000000103212147140046017646 0ustar billbillFunction: eint1 Section: transcendental C-Name: veceint1 Prototype: GDGp Help: eint1(x,{n}): exponential integral E1(x). If n is present, computes the vector of the first n values of the exponential integral E1(n.x) (x > 0). Doc: exponential integral $\int_x^\infty \dfrac{e^{-t}}{t}\,dt$ ($x\in\R$) If $n$ is present, outputs the $n$-dimensional vector $[\kbd{eint1}(x),\dots,\kbd{eint1}(nx)]$ ($x \geq 0$). This is faster than repeatedly calling \kbd{eint1($i$ * x)}. Variant: Also available is \fun{GEN}{eint1}{GEN x, long prec}. pari-2.5.5/src/functions/transcendental/exp0000644000175000017500000000060311636712103017426 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.5.5/src/functions/transcendental/bernvec0000644000175000017500000000133011636712103020254 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.5.5/src/functions/transcendental/acos0000644000175000017500000000074211636712103017563 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.5.5/src/functions/transcendental/zeta0000644000175000017500000000146611636712103017605 0ustar billbillFunction: zeta Section: transcendental C-Name: gzeta Prototype: Gp Help: zeta(s): Riemann zeta function at s with s a complex or a p-adic number. Doc: 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$). pari-2.5.5/src/functions/transcendental/incgamc0000644000175000017500000000063111636712103020234 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.5.5/src/functions/symbolic_operators/0000755000175000017500000000000012212611624017617 5ustar billbillpari-2.5.5/src/functions/symbolic_operators/or0000644000175000017500000000024411636712103020165 0ustar billbillFunction: _||_ C-Name: orpari Prototype: GE Help: x||y: inclusive OR. Section: symbolic_operators Description: (bool, bool):bool:parens $(1) || $(2) pari-2.5.5/src/functions/symbolic_operators/adde0000644000175000017500000000157411636712103020451 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.5.5/src/functions/symbolic_operators/sube0000644000175000017500000000157411636712103020512 0ustar billbillFunction: _-=_ C-Name: gsube 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 = subis($1, $2) (*int, int):int:parens $1 = subii($1, $2) (*real, small):real:parens $1 = subrs($1, $2) (*real, int):real:parens $1 = subri($1, $2) (*real, real):real:parens $1 = subrr($1, $2) (*mp, mp):mp:parens $1 = mpsub($1, $2) (*pol, small):gen:parens $1 = gsubgs($1, $2) (*pol, gen):gen:parens $1 = gsub($1, $2) (*vec, gen):gen:parens $1 = gsub($1, $2) (*gen, small):gen:parens $1 = gsubgs($1, $2) (*gen, gen):gen:parens $1 = gsub($1, $2) pari-2.5.5/src/functions/symbolic_operators/le0000644000175000017500000000143312147140046020145 0ustar billbillFunction: _<=_ Help: _<=_ 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.5.5/src/functions/symbolic_operators/lt0000644000175000017500000000132512147140046020164 0ustar billbillFunction: _<_ Help: _<_ Section: symbolic_operators C-Name: glt 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.5.5/src/functions/symbolic_operators/gt0000644000175000017500000000132512147140046020157 0ustar billbillFunction: _>_ Help: _>_ 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.5.5/src/functions/symbolic_operators/pow0000644000175000017500000000160111706644717020365 0ustar billbillFunction: _^_ Help: x^y: compute x to the power y. Section: symbolic_operators C-Name: gpow Prototype: GGp Description: (int, 2):int sqri($1) (int, 3):int powiu($1, 3) (int, 4):int powiu($1, 4) (int, 5):int powiu($1, 5) (real, -1):real invr($1) (mp, -1):mp ginv($1) (gen, -1):gen ginv($1) (real, 2):real sqrr($1) (mp, 2):mp mpsqr($1) (gen, 2):gen gsqr($1) (int, small):gen powis($1, $2) (real, small):real gpowgs($1, $2) (gen, small):gen gpowgs($1, $2) (real, int):real powgi($1, $2) (gen, int):gen powgi($1, $2) (gen, gen):gen:prec gpow($1, $2, prec) Function: _^s Help: return x^n where n is a small integer Section: programming/internals C-Name: gpowgs Prototype: GL pari-2.5.5/src/functions/symbolic_operators/mod0000644000175000017500000000071111636712103020323 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.5.5/src/functions/symbolic_operators/pl0000644000175000017500000000044511636712103020163 0ustar billbillFunction: +_ Help: +_ Section: symbolic_operators Description: (small):small:parens $1 (int):int:parens:copy $1 (real):real:parens:copy $1 (mp):mp:parens:copy $1 (gen):gen:parens:copy $1 pari-2.5.5/src/functions/symbolic_operators/and0000644000175000017500000000022611636712103020307 0ustar billbillFunction: _&&_ C-Name: andpari Prototype: GE Help: _&&_ Section: symbolic_operators Description: (bool, bool):bool:parens $(1) && $(2) pari-2.5.5/src/functions/symbolic_operators/eq0000644000175000017500000000225312147140046020153 0ustar billbillFunction: _==_ Help: _==_ Section: symbolic_operators C-Name: geq Prototype: GG Description: (small, small):bool:parens $(1) == $(2) (lg, lg):bool:parens $(1) == $(2) (small, int):bool:parens cmpsi($1, $2) == 0 (mp, 0):bool !signe($1) (int, 1):bool equali1($1) (int, -1):bool equalim1($1) (int, small):bool:parens cmpis($1, $2) == 0 (int, int):bool equalii($1, $2) (gen, 0):bool gequal0($1) (gen, 1):bool gequal1($1) (gen, -1):bool gequalm1($1) (real,real):bool cmprr($1, $2) == 0 (mp, mp):bool:parens mpcmp($1, $2) == 0 (typ, typ):bool:parens $(1) == $(2) (typ, #str):bool:parens $(1) == $(typ:2) (#str, typ):bool:parens $(typ:1) == $(2) (str, str):negbool strcmp($1, $2) (small, gen):bool gequalsg($1, $2) (gen, small):bool gequalgs($1, $2) (gen, gen):bool gequal($1, $2) pari-2.5.5/src/functions/symbolic_operators/mule0000644000175000017500000000150711636712103020512 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.5.5/src/functions/symbolic_operators/not0000644000175000017500000000025311636712103020345 0ustar billbillFunction: !_ Help: !_ Section: symbolic_operators C-Name: gnot Prototype: G Description: (negbool):bool:parens $1 (bool):negbool:parens $1 pari-2.5.5/src/functions/symbolic_operators/fact0000644000175000017500000000023311636712103020460 0ustar billbillFunction: _! Section: symbolic_operators C-Name: mpfact Prototype: L Help: n!: factorial of n. Description: (small):int mpfact($1) pari-2.5.5/src/functions/symbolic_operators/divround0000644000175000017500000000037511636712103021404 0ustar billbillFunction: _\/_ Help: x\/y: rounded Euclidean quotient of x and y. Section: symbolic_operators C-Name: gdivround Prototype: GG Description: (int, int):int gdivround($1, $2) (gen, gen):gen gdivround($1, $2) pari-2.5.5/src/functions/symbolic_operators/div0000644000175000017500000000125211636712103020327 0ustar billbillFunction: _/_ Section: symbolic_operators C-Name: gdiv Prototype: GG Help: x/y: quotient of x and y. Description: (0, mp):small ($2, 0)/*for side effect*/ (1, real):real invr($2) (#small, real):real divsr($1, $2) (small, real):mp divsr($1, $2) (real, small):real divrs($1, $2) (real, real):real divrr($1, $2) (real, mp):real mpdiv($1, $2) (mp, real):mp mpdiv($1, $2) (1, gen):gen ginv($2) (gen, small):gen gdivgs($1, $2) (small, gen):gen gdivsg($1, $2) (gen, gen):gen gdiv($1, $2) pari-2.5.5/src/functions/symbolic_operators/store0000644000175000017500000000016012147140046020675 0ustar billbillFunction: _=_ C-Name: gstore Prototype: m&G Section: symbolic_operators Help: x=y: store value y in variable x. pari-2.5.5/src/functions/symbolic_operators/shiftl0000644000175000017500000000035611636712103021042 0ustar billbillFunction: _<<_ Section: symbolic_operators C-Name: gshift Prototype: GL Help: x<>=_ 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.5.5/src/functions/symbolic_operators/divent0000644000175000017500000000102211636712103021031 0ustar billbillFunction: _\_ Section: symbolic_operators C-Name: gdivent Help: x\y: Euclidean quotient of x and y. Prototype: GG Description: (small, small):small:parens $(1)/$(2) (int, small):int truedivis($1, $2) (small, int):int gdiventsg($1, $2) (int, int):int truedivii($1, $2) (gen, small):gen gdiventgs($1, $2) (small, gen):gen gdiventsg($1, $2) (gen, gen):gen gdivent($1, $2) pari-2.5.5/src/functions/symbolic_operators/deriv0000644000175000017500000000027511636712103020662 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.5.5/src/functions/symbolic_operators/id0000644000175000017500000000017411636712103020143 0ustar billbillFunction: _===_ Help: a === b : true if a and b are identical Section: symbolic_operators C-Name: gidentical Prototype: iGG pari-2.5.5/src/functions/symbolic_operators/mode0000644000175000017500000000073411636712103020475 0ustar billbillFunction: _%=_ C-Name: gmode Prototype: &G Section: symbolic_operators Help: x%=y: shortcut for x=x%y. Description: (*small, small):small:parens $1 = smodss($1, $2) (*int, small):int:parens $1 = modis($1, $2) (*int, int):int:parens $1 = modii($1, $2) (*pol, gen):gen:parens $1 = gmod($1, $2) (*gen, small):gen:parens $1 = gmodgs($1, $2) (*gen, gen):gen:parens $1 = gmod($1, $2) pari-2.5.5/src/functions/symbolic_operators/neg0000644000175000017500000000044411636712103020320 0ustar billbillFunction: -_ Help: -_ Section: symbolic_operators C-Name: gneg Prototype: G Description: (small):small:parens -$(1) (int):int negi($1) (real):real negr($1) (mp):mp mpneg($1) (gen):gen gneg($1) pari-2.5.5/src/functions/symbolic_operators/concat0000644000175000017500000000044211636712103021014 0ustar billbillFunction: __ Help: __ Section: symbolic_operators Description: (genstr, genstr):genstr concat($1, $2) (genstr, gen):genstr concat($1, $2) (gen, genstr):genstr concat($1, $2) (gen, gen):genstr concat($genstr:1, $2) pari-2.5.5/src/functions/symbolic_operators/trans0000644000175000017500000000030611636712103020673 0ustar billbillFunction: _~ Section: symbolic_operators C-Name: gtrans Prototype: G Help: x~: transpose of x. Description: (vec):vec gtrans($1) (gen):gen gtrans($1) pari-2.5.5/src/functions/symbolic_operators/dive0000644000175000017500000000134611636712103020500 0ustar billbillFunction: _/=_ Section: symbolic_operators C-Name: gdive Prototype: &G Help: x/=y: shortcut for x=x/y. Description: (*small, gen):void $"cannot divide small: use \= instead." (*int, gen):void $"cannot divide int: use \= instead." (*real, real):real:parens $1 = divrr($1, $2) (*real, small):real:parens $1 = divrs($1, $2) (*real, mp):real:parens $1 = mpdiv($1, $2) (*mp, real):mp:parens $1 = mpdiv($1, $2) (*pol, gen):gen:parens $1 = gdiv($1, $2) (*vec, gen):gen:parens $1 = gdiv($1, $2) (*gen, small):gen:parens $1 = gdivgs($1, $2) (*gen, gen):gen:parens $1 = gdiv($1, $2) pari-2.5.5/src/functions/symbolic_operators/pp0000644000175000017500000000102411636712103020161 0ustar billbillFunction: _++ C-Name: gadd1e Prototype: & Section: symbolic_operators Help: x++ Description: (*bptr):bptr ++$1 (*small):small ++$1 (*lg):lg ++$1 (*int):int:parens $1 = addis($1, 1) (*real):real:parens $1 = addrs($1, 1) (*mp):mp:parens $1 = mpadd($1, gen_1) (*pol):pol:parens $1 = gaddgs($1, 1) (*gen):gen:parens $1 = gaddgs($1, 1) pari-2.5.5/src/functions/symbolic_operators/shiftr0000644000175000017500000000045411636712103021047 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.5.5/src/functions/symbolic_operators/shiftle0000644000175000017500000000055311636712103021206 0ustar billbillFunction: _<<=_ Section: symbolic_operators C-Name: gshiftle Prototype: &L Help: x<<=y: shortcut for x=x<=_ Help: _>=_ 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.5.5/src/functions/symbolic_operators/pound0000644000175000017500000000042411636712103020672 0ustar billbillFunction: #_ Section: symbolic_operators C-Name: glength Prototype: lG Help: #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) pari-2.5.5/src/functions/symbolic_operators/sub0000644000175000017500000000140311636712103020334 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.5.5/src/functions/symbolic_operators/divente0000644000175000017500000000060111636712103021200 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.5.5/src/functions/symbolic_operators/mul0000644000175000017500000000142011636712103020337 0ustar billbillFunction: _*_ Section: symbolic_operators C-Name: gmul Prototype: GG Help: x*y: product of x and y. Description: (small, small):small:parens $(1)*$(2) (int, small):int mulis($1, $2) (small, int):int mulsi($1, $2) (int, int):int mulii($1, $2) (0, mp):small ($2, 0)/*for side effect*/ (#small, real):real mulsr($1, $2) (small, real):mp mulsr($1, $2) (real, small):mp mulrs($1, $2) (real, real):real mulrr($1, $2) (mp, mp):mp mpmul($1, $2) (gen, small):gen gmulgs($1, $2) (small, gen):gen gmulsg($1, $2) (vecsmall, vecsmall):vecsmall perm_mul($1, $2) (gen, gen):gen gmul($1, $2) pari-2.5.5/src/functions/symbolic_operators/coeff0000644000175000017500000000137312147140046020632 0ustar billbillFunction: _[_,_] Class: symbolic_operators Description: (mp,small):gen $"Scalar has no components" (mp,small,small):gen $"Scalar has no components" (vecsmall,small):small $(1)[$2] (vecsmall,small,small):gen $"Vecsmall are single-dimensional" (list,small):gen:copy gel(list_data($1), $2) (vec,small):gen:copy gel($1, $2) (vec,small,small):gen:copy gcoeff($1, $2, $3) (gen,small):gen:copy gel($1, $2) (gen,small,small):gen:copy gcoeff($1, $2, $3) Function: _[_,] Class: symbolic_operators Help: x[y,]: y-th row of x. Description: (mp,small):gen $"Scalar has no rows" (vec,small):vec rowcopy($1, $2) (gen,small):vec rowcopy($1, $2) pari-2.5.5/src/functions/symbolic_operators/mm0000644000175000017500000000100411636712103020151 0ustar billbillFunction: _-- Section: symbolic_operators C-Name: gsub1e Prototype: & Help: x-- Description: (*bptr):bptr --$1 (*small):small --$1 (*lg):lg --$1 (*int):int:parens $1 = subis($1, 1) (*real):real:parens $1 = subrs($1, 1) (*mp):mp:parens $1 = mpsub($1, gen_1) (*pol):pol:parens $1 = gsubgs($1, 1) (*gen):gen:parens $1 = gsubgs($1, 1) pari-2.5.5/src/functions/symbolic_operators/hist0000644000175000017500000000015011636712103020510 0ustar billbillFunction: % C-Name: pari_get_hist Prototype: D0,L, Section: symbolic_operators Help: last history item. pari-2.5.5/src/functions/symbolic_operators/call0000644000175000017500000000046711636712103020467 0ustar billbillFunction: _(_) Class: symbolic_operators Help: f(a,b,...): evaluates the function f on a,b,... Description: (gen):gen closure_callgenall($1, 0) (gen,gen):gen closure_callgen1($1, $2) (gen,gen,gen):gen closure_callgen2($1, $2, $3) (gen,gen,...):gen closure_callgenall($1, ${nbarg 1 sub}, $3) pari-2.5.5/src/functions/sums/0000755000175000017500000000000012212611624014667 5ustar billbillpari-2.5.5/src/functions/sums/intcirc0000644000175000017500000000150411636712103016250 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.5.5/src/functions/sums/prodinf0000644000175000017500000000160511636712103016260 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.5.5/src/functions/sums/intlaplaceinv0000644000175000017500000000437411636712103017456 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.5.5/src/functions/sums/prod0000644000175000017500000000263011636712103015562 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.5.5/src/functions/sums/sumnuminit0000644000175000017500000000105711636712103017030 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.5.5/src/functions/sums/solve0000644000175000017500000000131011636712103015740 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.5.5/src/functions/sums/sumalt0000644000175000017500000000404511636712103016125 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.5.5/src/functions/sums/intfouriersin0000644000175000017500000000153111636712103017515 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.5.5/src/functions/sums/intfuncinit0000644000175000017500000000302512147140046017146 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.5.5/src/functions/sums/sumnum0000644000175000017500000001153111636712103016142 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.5.5/src/functions/sums/intnum0000644000175000017500000002736212147140046016140 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.5.5/src/functions/sums/sumnumalt0000644000175000017500000000463711636712103016654 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.5.5/src/functions/sums/intmellininv0000644000175000017500000000402711636712103017330 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.5.5/src/functions/sums/intfouriercos0000644000175000017500000000153611636712103017515 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.5.5/src/functions/sums/intnuminit0000644000175000017500000000362511636712103017021 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.5.5/src/functions/sums/sum0000644000175000017500000000121011636712103015413 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.5.5/src/functions/sums/intnumstep0000644000175000017500000000052611636712103017026 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.5.5/src/functions/sums/intnumromb0000644000175000017500000000515111636712103017011 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$. This function is deprecated, use \tet{intnum} instead. 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 1e1000. However beware of real underflow when dealing with rapidly decreasing functions. For example, if one wants to compute the $\int_0^\infty e^{-x^2}\,dx$ to 28 decimal digits, then one should set infinity equal to 10 for example, and certainly not to 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.5.5/src/functions/sums/prodeuler0000644000175000017500000000076311636712103016624 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.5.5/src/functions/sums/derivnum0000644000175000017500000000200012147140046016435 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.5.5/src/functions/sums/sumdiv0000644000175000017500000000126412147140046016126 0ustar billbillFunction: sumdiv Section: sums C-Name: divsum 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). Arithmetic functions like \tet{sigma} use the multiplicativity of the underlying expression to speed up the computation. Since there is no way to indicate that \var{expr} is multiplicative in $n$, specialized functions should always be preferred. %\syn{NO} pari-2.5.5/src/functions/sums/intfourierexp0000644000175000017500000000161011636712103017516 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.5.5/src/functions/sums/intmellininvshort0000644000175000017500000000403511636712103020407 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.5.5/src/functions/sums/intnuminitgen0000644000175000017500000000171611636712103017512 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.5.5/src/functions/sums/sumpos0000644000175000017500000000260511636712103016146 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.5.5/src/functions/sums/suminf0000644000175000017500000000220011636712103016110 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.5.5/src/functions/gp2c_internal/0000755000175000017500000000000012212611624016427 5ustar billbillpari-2.5.5/src/functions/gp2c_internal/_typedef0000644000175000017500000000345112147140046020156 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 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 (genstr) GEN (str) char* (bptr) byteptr (func_GG) func_GG (pari_sp) pari_sp (typ) long (nf) GEN (bnf) GEN (bnr) GEN (ell) GEN (bell) 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.5.5/src/functions/gp2c_internal/_tovec0000644000175000017500000000133211636712103017633 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,...):vec mkvecn($#, $2) Function: _tovecprec Class: gp2c_internal Help: Create a vector holding the arguments and prec (shallow) Description: ():vec:prec mkvecs(prec) (gen):vec:prec mkvec2($1, stoi(prec)) (gen,gen):vec:prec mkvec3($1, $2, stoi(prec)) (gen,gen,gen):vec:prec mkvec4($1, $2, $3, stoi(prec)) (gen,...):vec:prec mkvecn(${nbarg 1 add}, $2, stoi(prec)) pari-2.5.5/src/functions/gp2c_internal/_maxprime0000644000175000017500000000013211636712103020332 0ustar billbillFunction: _maxprime Class: gp2c_internal Description: ():small maxprime() pari-2.5.5/src/functions/gp2c_internal/_strtoclosure0000644000175000017500000000025311636712103021264 0ustar billbillFunction: _strtoclosure Class: gp2c_internal Description: (str):closure strtofunction($1) (str,gen,...):closure strtoclosure($1, ${nbarg 1 sub}, $3) pari-2.5.5/src/functions/gp2c_internal/_gerepileall0000644000175000017500000000030111636712103020773 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.5.5/src/functions/gp2c_internal/_toGENstr0000644000175000017500000000020612147140046020216 0ustar billbillFunction: _toGENstr Class: gp2c_internal Description: (str):genstr strtoGENstr($1) (gen):genstr GENtoGENstr($1) pari-2.5.5/src/functions/gp2c_internal/_gerepileupto0000644000175000017500000000053011636712103021216 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.5.5/src/functions/gp2c_internal/_avma0000644000175000017500000000012211636712103017433 0ustar billbillFunction: _avma Class: gp2c_internal Description: ():pari_sp avma pari-2.5.5/src/functions/gp2c_internal/_const0000644000175000017500000000073611636712103017650 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.5.5/src/functions/gp2c_internal/_cgetg0000644000175000017500000000024011636712103017601 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.5.5/src/functions/gp2c_internal/_formatcode0000644000175000017500000000036411636712103020642 0ustar billbillFunction: _formatcode Class: gp2c_internal Description: (#small):void $1 (small):small %ld (#str):void $%1 (str):str %s (gen):gen %Ps pari-2.5.5/src/functions/gp2c_internal/_cast0000644000175000017500000000540712147140046017453 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, vecsmall, gen) (empty, vec, gen) (empty, list, gen) (empty, closure, gen) (empty, bnr, bnf, nf, vec) (empty, bnr, bnf, clgp, vec) (empty, bell, 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):closure (gen):vecsmall (nf):vec (bnf):vec (bnr):vec (ell):vec (bell):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 (closure):gen (gen):genstr GENtoGENstr($1) (str):genstr strtoGENstr($1) (genstr):str GSTR($1) (typ):str type_name($1) (#str):typ ${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 (bell):ell (gen):ell (gen):bell (gen):gal (gen):prid pari-2.5.5/src/functions/gp2c_internal/_stack_lim0000644000175000017500000000034311636712103020462 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.5.5/src/functions/gp2c_internal/_badtype0000644000175000017500000000150212147140046020141 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):bool:parens lg($1) != 3 || typ($(1)[2]) != t_POLMOD (ell):void checksmallell($1) (bell):void checkell($1) (*gal):gal:parens $1 = checkgal($1) pari-2.5.5/src/functions/gp2c_internal/_wrap0000644000175000017500000000047011636712103017466 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.5.5/src/functions/conversions/0000755000175000017500000000000012212611624016250 5ustar billbillpari-2.5.5/src/functions/conversions/Vecrev0000644000175000017500000000076512147140046017437 0ustar billbillFunction: Vecrev Section: conversions C-Name: gtovecrev Prototype: DG Help: Vecrev({x=[]}): transforms the object x into a vector. Empty vector if x is omitted. Description: ():vec cgetg(1,t_VEC) (gen):vec gtovecrev($1) Doc: as $\kbd{Vec}(x)$, 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. pari-2.5.5/src/functions/conversions/Polrev0000644000175000017500000000162112147140046017444 0ustar billbillFunction: Polrev Section: conversions C-Name: gtopolyrev Prototype: GDn Description: (gen,?var):pol gtopolyrev($1, $2) Help: Polrev(x,{v=x}): convert x (usually a vector or a power series) into a polynomial with variable v, starting with the constant term. Doc: transform the object $x$ into a polynomial with main variable $v$. If $x$ is a scalar, this gives a constant polynomial. If $x$ 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 $x$ is a vector: it creates the polynomial whose coefficients are given by $x$, with $x[1]$ being the constant term. \tet{Pol} can be used if one wants $x[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.5.5/src/functions/conversions/bitand0000644000175000017500000000156311636712103017444 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.5.5/src/functions/conversions/numerator0000644000175000017500000000163211636712103020214 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.5.5/src/functions/conversions/precision0000644000175000017500000000535012147140046020173 0ustar billbillFunction: precision Section: conversions C-Name: precision0 Prototype: GD0,L, Help: precision(x,{n}): change the precision of x to be n. If n is omitted, output 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: gives 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 not omitted, 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; tor 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.5.5/src/functions/conversions/bitnegimply0000644000175000017500000000130211636712103020515 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.5.5/src/functions/conversions/norml20000644000175000017500000000145211636712103017411 0ustar billbillFunction: norml2 Section: conversions C-Name: gnorml2 Prototype: G Help: norml2(x): square of the L2-norm of the vector x. Doc: square of the $L^2$-norm of $x$. More precisely, if $x$ is a scalar, $\kbd{norml2}(x)$ is defined to be \kbd{$x$ * conj($x$)}. 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.5.5/src/functions/conversions/real0000644000175000017500000000036411636712103017124 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.5.5/src/functions/conversions/sizebyte0000644000175000017500000000052711636712103020040 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.5.5/src/functions/conversions/floor0000644000175000017500000000100211636712103017310 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.5.5/src/functions/conversions/permtonum0000644000175000017500000000043312147140046020223 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}. pari-2.5.5/src/functions/conversions/Ser0000644000175000017500000000174412147140046016734 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 with precision \kbd{d}. If $s$ is a polynomial, the precision is the maximum of \kbd{d} and the degree of the polynomial. 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}$(x)$), and the precision $d$ is ignored. \bprog ? Ser(x^2,, 5) %1 = x^2 + O(x^7) ? Ser([1,2,3], t) %2 = 1 + 2*t + 3*t^2 + O(t^3) @eprog\noindent The warning given for \kbd{Pol} also applies here: this is not a substitution function. pari-2.5.5/src/functions/conversions/conj0000644000175000017500000000062111636712103017126 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.5.5/src/functions/conversions/numtoperm0000644000175000017500000000051612147140046020225 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}. pari-2.5.5/src/functions/conversions/variable0000644000175000017500000000207411636712103017766 0ustar billbillFunction: variable Section: conversions C-Name: gpolvar Prototype: DG Help: variable({x}): main variable of object x. Gives p for p-adic x, error for scalars. 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$, and $p$ if $x$ is a $p$-adic number. Gives an error if $x$ has no variable associated to it. 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.5.5/src/functions/conversions/imag0000644000175000017500000000036611636712103017120 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.5.5/src/functions/conversions/Vecsmall0000644000175000017500000000117612147140046017750 0ustar billbillFunction: Vecsmall Section: conversions C-Name: gtovecsmall Prototype: DG Help: Vecsmall({x=[]}): transforms the object x into a VECSMALL. Empty vector if x is omitted. Description: (gen):vecsmall gtovecsmall($1) Doc: transforms the object $x$ into a row vector of type \typ{VECSMALL}. This acts as \kbd{Vec}, but only on a limited set of objects (the result must be representable as a vector of small integers). In particular, polynomials and power series are forbidden. If $x$ is a character string, a vector of individual characters in ASCII encoding is returned (\tet{Strchr} yields back the character string). pari-2.5.5/src/functions/conversions/sizedigit0000644000175000017500000000053611636712103020175 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.5.5/src/functions/conversions/valuation0000644000175000017500000000166412147140046020206 0ustar billbillFunction: valuation Section: conversions C-Name: ggval 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.5.5/src/functions/conversions/Mat0000644000175000017500000000163411636712103016723 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.5.5/src/functions/conversions/length0000644000175000017500000000201311636712103017453 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.5.5/src/functions/conversions/conjvec0000644000175000017500000000150611636712103017627 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.5.5/src/functions/conversions/norm0000644000175000017500000000066111636712103017154 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.5.5/src/functions/conversions/Vec0000644000175000017500000000175012147140046016715 0ustar billbillFunction: Vec Section: conversions C-Name: gtovec Prototype: DG Help: Vec({x=[]}): transforms the object x into a vector. Empty vector if x is omitted. Description: ():vec cgetg(1,t_VEC) (gen):vec gtovec($1) Doc: transforms the object $x$ into a row vector. That 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 matrix (the vector of columns comprising the matrix is return), \item a character string (a vector of individual characters is returned), \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. pari-2.5.5/src/functions/conversions/Strexpand0000644000175000017500000000112011636712103020140 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.5.5/src/functions/conversions/lift0000644000175000017500000000243612147140046017140 0ustar billbillFunction: lift Section: conversions C-Name: lift0 Prototype: GDn Help: lift(x,{v}): lifts every element of Z/nZ to Z or T[x]/PT[x] to T[x] for a type T if v is omitted, otherwise lift only polmods with main variable v. If v does not occur in x, lift only intmods. 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: lifts an element $x=a \bmod n$ of $\Z/n\Z$ to $a$ in $\Z$, and similarly lifts a polmod to a polynomial if $v$ is omitted. Otherwise, lifts only polmods whose modulus has main variable $v$ (if $v$ does not occur in $x$, lifts only intmods). If $x$ is of recursive (non modular) type, the lift is done coefficientwise. For $p$-adics, this routine acts as \tet{truncate}. It is not allowed to have $x$ of type \typ{REAL}. \bprog ? lift(Mod(5,3)) %1 = 2 ? lift(3 + O(3^9)) %2 = 3 ? lift(Mod(x,x^2+1)) %3 = x ? 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(2, y^2+1) @eprog Variant: Also available is \fun{GEN}{lift}{GEN x} corresponding to \kbd{lift0(x,-1)}. pari-2.5.5/src/functions/conversions/centerlift0000644000175000017500000000215111636712103020334 0ustar billbillFunction: centerlift Section: conversions C-Name: centerlift0 Prototype: GDn Help: centerlift(x,{v}): centered lift of x. Same as lift except for integermods. 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: lifts an element $x=a \bmod n$ of $\Z/n\Z$ to $a$ in $\Z$, and similarly lifts a polmod to a polynomial. This is the same as \tet{lift} except that in the particular case of elements of $\Z/n\Z$, the lift $y$ is such that $-n/20. 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.5.5/src/functions/conversions/Mod0000644000175000017500000000131311636712103016713 0ustar billbillFunction: Mod Section: conversions C-Name: gmodulo Prototype: GG Help: Mod(x,y): creates 'x modulo y'. Description: (small, small):gen gmodulss($1, $2) (small, gen):gen gmodulsg($1, $2) (gen, gen):gen gmodulo($1, $2) Doc: creates the PARI object $(x \mod y)$, i.e.~an intmod or a polmod. $y$ must be an integer or a polynomial. If $y$ is an integer, $x$ must be an integer, a rational number, or a $p$-adic number compatible with the modulus $y$. If $y$ is a polynomial, $x$ must be a scalar (which is not a polmod), a polynomial, a rational function, or a power series. This function is not the same as $x$ \kbd{\%} $y$, the result of which is an integer or a polynomial. pari-2.5.5/src/functions/conversions/bitor0000644000175000017500000000115011636712103017312 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.5.5/src/functions/conversions/Str0000644000175000017500000000141212147140046016743 0ustar billbillFunction: Str Section: conversions C-Name: Str Prototype: s* Help: Str({x}*): concatenates its (string) argument into a single string. Description: (gen):genstr:copy:parens $genstr:1 Doc: 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} pari-2.5.5/src/functions/conversions/random0000644000175000017500000000571012147140046017460 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). 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} 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 an abscissa is drawn uniformly at random until \tet{ellordinate} succeeds. In particular, the curves over $\F_2$ with a single point (at infinity!) will trigger an infinite loop. Note that this is definitely not a uniform distribution over $E(k)$. \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([0,0,0,3,7]*Mod(1,109)); random(E) %4 = [Mod(103, 109), Mod(10, 109)] ? E = ellinit([0,0,0,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 the system's random number generator. 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. \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.5.5/src/functions/conversions/round0000644000175000017500000000302711636712103017327 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.5.5/src/functions/conversions/denominator0000644000175000017500000000212111636712103020511 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.5.5/src/functions/conversions/simplify0000644000175000017500000000176211636712103020040 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.5.5/src/functions/conversions/component0000644000175000017500000000316712147140046020206 0ustar billbillFunction: component Section: conversions C-Name: compo Prototype: GL Help: component(x,n): the n'th component of the internal representation of x. For vectors or matrices, it is simpler to use x[]. For list objects such as nf, bnf, bnr or ell, it is much easier to use member functions starting with ".". Doc: extracts the $n^{\text{th}}$-component of $x$. This is to be understood as follows: every PARI type has one or two initial \idx{code words}. The components are counted, starting at 1, after these code words. In particular if $x$ is a vector, this is indeed the $n^{\text{th}}$-component of $x$, if $x$ is a matrix, the $n^{\text{th}}$ column, if $x$ is a polynomial, the $n^{\text{th}}$ coefficient (i.e.~of degree $n-1$), and for power series, the $n^{\text{th}}$ significant coefficient. For polynomials and power series, one should rather use \tet{polcoeff}, and for vectors and matrices, the \kbd{[$\,$]} operator. Namely, if $x$ is a vector, then \tet{x[n]} represents the $n^{\text{th}}$ component of $x$. If $x$ is a matrix, \tet{x[m,n]} represents the coefficient of row \kbd{m} and column \kbd{n} of the matrix, \tet{x[m,]} represents the $m^{\text{th}}$ \emph{row} of $x$, and \tet{x[,n]} represents the $n^{\text{th}}$ \emph{column} of $x$. Using of this function requires detailed knowledge of the structure of the different PARI types, and thus it should almost never be used directly. Some useful exceptions: \bprog ? x = 3 + O(3^5); ? component(x, 2) %2 = 81 \\ p^(p-adic acurracy) ? component(x, 1) %3 = 3 \\ p ? q = Qfb(1,2,3); ? component(q, 1) %5 = 1 @eprog pari-2.5.5/src/functions/conversions/Strprintf0000644000175000017500000000063511636712103020175 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.5.5/src/functions/conversions/ceil0000644000175000017500000000100111636712103017102 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.5.5/src/functions/conversions/binary0000644000175000017500000000056211636712103017465 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.5.5/src/functions/conversions/Set0000644000175000017500000000146212147140046016733 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 of character strings, with strictly increasing entries with respect to lexicographic ordering. The components of $x$ are put in canonical form (type \typ{STR}) so as to be easily sorted. To recover an ordinary \kbd{GEN} from such an element, you can apply \tet{eval} to it. Note that most set functions also accept ordinary vectors, provided their components can be compared with \kbd{<}. Sets as created by this function are only useful when e.g. polynomial or vector entries are involved. pari-2.5.5/src/functions/conversions/bittest0000644000175000017500000000144312147140046017655 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. pari-2.5.5/src/functions/conversions/bitneg0000644000175000017500000000113012147140046017440 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, 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.5.5/src/functions/conversions/truncate0000644000175000017500000000325511636712103020030 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.5.5/src/functions/conversions/Col0000644000175000017500000000207512147140046016716 0ustar billbillFunction: Col Section: conversions C-Name: gtocol Prototype: DG Help: Col({x=[]}): transforms the object x into a column vector. Empty vector if x is omitted. Description: ():vec cgetg(1,t_COL) (gen):vec gtocol($1) Doc: transforms the object $x$ into a column vector. 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 column vector), \item a matrix (the column of row vectors comprising the matrix is returned), \item a character string (a column of individual characters is returned), \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{Col} is the reciprocal function of \kbd{Pol} and \kbd{Ser} respectively. Note that the function \kbd{Colrev} does not exist, use \kbd{Vecrev}. pari-2.5.5/src/functions/programming/0000755000175000017500000000000012212611624016222 5ustar billbillpari-2.5.5/src/functions/programming/select0000644000175000017500000000246512147140046017435 0ustar billbillFunction: select Section: programming/specific C-Name: select0 Prototype: GG Help: select(f, A): selects elements of A according to the selection function f. Wrapper: (bG) Description: (gen,gen):gen genselect(${1 cookie}, ${1 wrapper}, $2) Doc: Given a vector, list or matrix \kbd{A} and a \typ{CLOSURE} \kbd{f}, 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 following function lists the elements in $(\Z/N\Z)^*$: \bprog ? invertibles(N) = select(x->gcd(x,N) == 1, vector(N,i,i)) @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}. pari-2.5.5/src/functions/programming/apply0000644000175000017500000000223412147140046017275 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 \synt{genapply}{void *E, GEN (*fun)(void*,GEN), GEN a}. pari-2.5.5/src/functions/programming/warning0000644000175000017500000000077112147140046017621 0ustar billbillFunction: warning Section: programming/specific C-Name: warning0 Prototype: vs* Help: warning({str}*): display warning message str Description: (?gen,...):void pari_warn(user, "${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.5.5/src/functions/programming/default0000644000175000017500000000340211636712103017573 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.5.5/src/functions/programming/getheap0000644000175000017500000000055111636712103017566 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.5.5/src/functions/programming/local0000644000175000017500000000017511636712103017245 0ustar billbillFunction: local Section: programming/specific Help: local(x,...,z): declare x,...,z as (dynamically scoped) local variables. pari-2.5.5/src/functions/programming/print0000644000175000017500000000051511636712103017305 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.5.5/src/functions/programming/my0000644000175000017500000000016311636712103016575 0ustar billbillFunction: my Section: programming/specific Help: my(x,...,z): declare x,...,z as lexically-scoped local variables. pari-2.5.5/src/functions/programming/return0000644000175000017500000000043711636712103017473 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.5.5/src/functions/programming/read0000644000175000017500000000150311636712103017062 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.5.5/src/functions/programming/until0000644000175000017500000000064511636712103017310 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.5.5/src/functions/programming/for0000644000175000017500000000043511636712103016740 0ustar billbillFunction: for Section: programming/control C-Name: forpari Prototype: vV=GGI Help: for(X=a,b,seq): the sequence is evaluated, X going from a up to b. Doc: 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$. pari-2.5.5/src/functions/programming/forsubgroup0000644000175000017500000000345211636712103020531 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 (in SNF form), whose index is bounded by bound. 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), whose index is bounded by $B$. 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.5.5/src/functions/programming/quit0000644000175000017500000000067711636712103017144 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.5.5/src/functions/programming/trap0000644000175000017500000000407612147140046017124 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 ommitted); sequence rec is executed if the error occurs and is the result of the command. Wrapper: (,_,_) Description: (?str,?closure,?closure):gen trap0($1, $2, $3) Doc: 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 (gdiver, 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{alarmer}: alarm time-out \kbd{archer}: not available on this architecture or operating system \kbd{errpile}: the PARI stack overflows \kbd{gdiver}: division by 0 \kbd{impl}: not yet implemented \kbd{invmoder}: impossible inverse modulo \kbd{overflower}: all forms of arithmetic overflow, including length or exponent overflow (when a larger value is supplied than the implementation can handle). \kbd{syntaxer}: syntax error \kbd{talker}: miscellaneous error \kbd{typeer}: wrong type \kbd{user}: user error (from the \kbd{error} function) pari-2.5.5/src/functions/programming/break0000644000175000017500000000075211636712103017240 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.5.5/src/functions/programming/forstep0000644000175000017500000000110711636712103017631 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 $a= 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, 0, "git-2cce227"] \\ development @eprog In particular the first line of the gp introductory message can be essentially emulated by \bprog v = version(); n = Str(v[1], ".", v[2], ".", v[3]); s = if (#v > 3, v[4], ""); print("GP/PARI CALCULATOR Version ", n, " (", s, ")"); @eprog\noindent If you \emph{are} working with many development versions of PARI/GP, the last component can be profitably included in the name of your logfile, for instance. pari-2.5.5/src/functions/programming/addhelp0000644000175000017500000000156411636712103017557 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}. If \kbd{sym} is a function \emph{you} have defined, its definition will still be printed before the message \var{str}. It is recommended that you document global variables and user functions in this way. Of course \kbd{gp} will not protest if you skip this. It is possible to 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 functions 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 to do it! pari-2.5.5/src/functions/programming/forprime0000644000175000017500000000163112147140046017773 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 Section: programming/control C-Name: forprime Prototype: vV=GGI Help: forprime(X=a,b,seq): the sequence is evaluated, X running over the primes between a and b. Doc: evaluates \var{seq}, where the formal variable $X$ ranges over the prime numbers between $a$ to $b$ (including $a$ and $b$ if they are prime). More precisely, the value of $X$ is incremented to the smallest prime strictly larger than $X$ at the end of each iteration. Nothing is done if $a>b$. Note that $a$ and $b$ must be in $\R$. \bprog f(N) = { forprime(p = 2, N, print(p); if (p == 3, p = 6); ) } ? f(12) 2 3 7 11 @eprog pari-2.5.5/src/functions/programming/alarm0000644000175000017500000000130512147140046017242 0ustar billbillFunction: alarm Class: gp Section: programming/specific C-Name: alarm0 Prototype: vD0,L, Help: alarm({s = 0}): trigger an "alarmer" exception after s seconds, cancelling any previously set alarm. Stop a pending alarm if s = 0 or is omitted. Doc: trigger an \var{alarmer} exception after $s$ seconds, cancelling any previously set alarm. Stop a pending alarm if s = 0 or is omitted. For example, the function \kbd{timefact(N,sec)} below will try to factor $N$ and give up after \var{sec} seconds, returning a partial factorisation. \bprog default(factor_add_primes,1); default(primelimit,16777216); timefact(N,sec)= { trap(alarmer,factor(N,0),alarm(sec);my(F=factor(N));alarm(0);F); } @eprog pari-2.5.5/src/functions/programming/whatnow0000644000175000017500000000066211636712103017643 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.5.5/src/functions/programming/alias0000644000175000017500000000346311636712103017247 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.5.5/src/functions/programming/input0000644000175000017500000000136211636712103017311 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.5.5/src/functions/programming/allocatemem0000644000175000017500000000334611636712103020441 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 very special operation allows the user to change the stack size \emph{after} initialization. $x$ must be a non-negative integer. If $x \neq 0$, a new stack of size $16*\ceil{x/16}$ bytes is allocated. 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}. pari-2.5.5/src/functions/programming/global0000644000175000017500000000024511636712103017411 0ustar billbillFunction: global Section: programming/specific Help: global(list of variables): obsolete. Scheduled for deletion. Doc: obsolete. Scheduled for deletion. % \syn{NO} pari-2.5.5/src/functions/programming/_eval_mnemonic0000644000175000017500000000021011636712103021114 0ustar billbillFunction: _eval_mnemonic C-Name: eval_mnemonic Section: programming/internals Prototype: lGs Help: Convert a mnemonic string to a flag. pari-2.5.5/src/functions/programming/if0000644000175000017500000000274012147140046016550 0ustar billbillFunction: _void_if C-Name: ifpari_void Section: programming/internals Prototype: vGDIDI Help: internal variant of if() that does not return a value. Function: 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})}. Note that the boolean operators \kbd{\&\&} and \kbd{||} are evaluated according to operator precedence as explained in \secref{se:operators}, but that, 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 (reallydoit && longcomplicatedfunction(), ...) @eprog \noindent is a perfectly safe statement. Recall that 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!). pari-2.5.5/src/functions/programming/gettime0000644000175000017500000000052011636712103017603 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. pari-2.5.5/src/functions/programming/while0000644000175000017500000000061311636712103017260 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.5.5/src/functions/programming/getrand0000644000175000017500000000067211636712103017601 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.5.5/src/functions/programming/readvec0000644000175000017500000000170711636712103017566 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.5.5/src/functions/programming/writebin0000644000175000017500000000365312147140046020001 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}). 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. User functions, installed functions and history objects can not be saved via this function. 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.5.5/src/functions/programming/fordiv0000644000175000017500000000205311636712103017441 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.5.5/src/functions/programming/system0000644000175000017500000000063112147140046017473 0ustar billbillFunction: system Class: gp Section: programming/specific C-Name: system0 Prototype: vs 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.5.5/src/functions/programming/setrand0000644000175000017500000000077011636712103017614 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.5.5/src/functions/programming/externstr0000644000175000017500000000071211636712103020206 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.5.5/src/functions/programming/extern0000644000175000017500000000062011636712103017453 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.5.5/src/functions/programming/type0000644000175000017500000000114011636712103017125 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.5.5/src/functions/programming/writetex0000644000175000017500000000037011636712103020023 0ustar billbillFunction: writetex Section: programming/specific C-Name: writetex Prototype: vss* Help: writetex(filename,{str}*): appends the remaining arguments (same format as print) to filename, in TeX format. Doc: as \kbd{write}, in \TeX\ format. %\syn{NO} pari-2.5.5/src/functions/programming/write0000644000175000017500000000046111636712103017303 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.5.5/src/functions/programming/print10000644000175000017500000000066511636712103017374 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.5.5/src/functions/programming/next0000644000175000017500000000101111636712103017117 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.5.5/src/functions/programming/printf0000644000175000017500000001717511636712103017465 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.5.5/src/functions/programming/error0000644000175000017500000000117512147140046017304 0ustar billbillFunction: _err_primes Class: gp2c_internal Description: ():void pari_err(primer1) Function: _err_type Class: gp2c_internal Description: (str):void pari_err(typeer, $1) Function: error Section: programming/specific C-Name: error0 Prototype: vs* Help: error({str}*): abort script with error message str. Description: (?gen,...):void pari_err(talker, "${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.5.5/src/functions/programming/write10000644000175000017500000000047111636712103017365 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.5.5/src/functions/programming/install0000644000175000017500000000367512147140046017630 0ustar billbillFunction: install Class: highlevel 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 argument code 'code'. If 'lib' is omitted use 'libpari.so'. 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 argument code \var{code} (see the Libpari Manual for an explanation of those). If \var{lib} is omitted, uses \kbd{libpari.so}. If \var{gpname} is omitted, uses \var{name}. This function is useful for adding custom functions to the \kbd{gp} interpreter, or picking useful functions from unrelated libraries. For instance, it makes the function \tet{system} obsolete: \bprog ? install(system, vs, sys, "libc.so") ? sys("ls gp*") gp.c gp.h gp_rl.c @eprog But it also 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 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 it the latter has been recompiled. \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, i.e.~a major internal blunder (this should never happen with a dynamically linked executable). Hence, if you intend to use this function, please check first on some harmless example such as the ones above that it works properly on your machine. pari-2.5.5/src/functions/programming/kill0000644000175000017500000000267511636712103017115 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.5.5/src/functions/programming/getstack0000644000175000017500000000043511636712103017757 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.5.5/src/functions/polynomials/0000755000175000017500000000000012212611624016246 5ustar billbillpari-2.5.5/src/functions/polynomials/poldegree0000644000175000017500000000143511636712103020145 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.5.5/src/functions/polynomials/polsubcyclo0000644000175000017500000000135112147140046020531 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 is 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 more closely which sub-Abelian extension should be computed. pari-2.5.5/src/functions/polynomials/polinterpolate0000644000175000017500000000135511636712103021241 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.5.5/src/functions/polynomials/serlaplace0000644000175000017500000000051211636712103020305 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.5.5/src/functions/polynomials/polsym0000644000175000017500000000043511636712103017521 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.5.5/src/functions/polynomials/polsturm0000644000175000017500000000101311636712103020054 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.5.5/src/functions/polynomials/factorpadic0000644000175000017500000000156711636712103020464 0ustar billbillFunction: factorpadic Section: polynomials C-Name: factorpadic0 Prototype: GGLD0,L, Help: factorpadic(pol,p,r,{flag=0}): p-adic factorization of the polynomial pol to precision r. flag is optional and may be set to 0 (use round 4) or 1 (use Buchmann-Lenstra). Doc: $p$-adic factorization of the polynomial \var{pol} to precision $r$, the result being a two-column matrix as in \kbd{factor}. The factors are normalized so that their leading coefficient is a power of $p$. $r$ must be strictly larger than the $p$-adic valuation of the discriminant of \var{pol} for the result to make any sense. The method used is a modified version of the \idx{round 4} algorithm of \idx{Zassenhaus}. If $\fl=1$, use an algorithm due to \idx{Buchmann} and \idx{Lenstra}, which is much less efficient. Variant: \fun{GEN}{factorpadic}{GEN f,GEN p, long r} corresponds to the default $\fl=0$. pari-2.5.5/src/functions/polynomials/thue0000644000175000017500000000433312147140046017143 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. 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. 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 favourable 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 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.ref %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.5.5/src/functions/polynomials/thueinit0000644000175000017500000000174111636712103020030 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 unconditionnaly. 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.5.5/src/functions/polynomials/taylor0000644000175000017500000000127611636712103017514 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.5.5/src/functions/polynomials/padicappr0000644000175000017500000000120212147140046020131 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$. pari-2.5.5/src/functions/polynomials/polcoeff0000644000175000017500000000204312147140046017767 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, vector or matrix types are also accepted for $x$, and the meaning is then identical with that of \kbd{component(x,n)}. pari-2.5.5/src/functions/polynomials/serconvol0000644000175000017500000000051511636712103020207 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.5.5/src/functions/polynomials/substvec0000644000175000017500000000122611636712103020033 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.5.5/src/functions/polynomials/eval0000644000175000017500000000144412147140046017125 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. For convenience, $x$ is evaluated as if \kbd{strictmatch} was off. In particular, unused characters at the end of $x$ do not prevent its evaluation: \bprog ? eval("1a") *** eval: Warning: unused characters: a. % 1 = 1 @eprog \synt{geval}{GEN x}. pari-2.5.5/src/functions/polynomials/diffop0000644000175000017500000000362611636712103017452 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.5.5/src/functions/polynomials/serreverse0000644000175000017500000000037511636712103020366 0ustar billbillFunction: serreverse Section: polynomials C-Name: recip Prototype: G Help: serreverse(x): reversion of the power series x. Doc: reverse power series (i.e.~$x^{-1}$, not $1/x$) of $x$. $x$ must be a power series whose valuation is exactly equal to one. pari-2.5.5/src/functions/polynomials/polchebyshev0000644000175000017500000000222512147140046020667 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}{polchebyshev1}{long n, long v} and \fun{GEN}{polchebyshev2}{long n, long v} for $T_n$ and $U_n$ respectively. pari-2.5.5/src/functions/polynomials/polroots0000644000175000017500000000255312147140046020061 0ustar billbillFunction: polroots Section: polynomials C-Name: roots0 Prototype: GD0,L,p Help: polroots(x,{flag=0}): complex roots of the polynomial x. flag is optional, and can be 0: default, uses Schonhage's method modified by Gourdon, or 1: uses a modified Newton method. Doc: complex roots of the polynomial \var{pol}, 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 implemented by X.~Gourdon. Barring bugs, it is guaranteed to converge and to give the roots to the required accuracy. If $\fl=1$, use a variant of the Newton-Raphson method, which is \emph{not} guaranteed to converge, nor to give accurate results, but is rather fast when it does. If you get the messages ``too many iterations in roots'' or ``INTERNAL ERROR: incorrect result in roots'', use the default algorithm. Variant: Also available is \fun{GEN}{roots}{GEN x, long prec}, as well as \fun{GEN}{cleanroots}{GEN x, long prec} which ensures that real roots of real polynomials are returned as \typ{REAL} (instead of \typ{COMPLEX}s with 0 imaginary part). pari-2.5.5/src/functions/polynomials/substpol0000644000175000017500000000211711636712103020050 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.5.5/src/functions/polynomials/O0000644000175000017500000000153711636712103016400 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.5.5/src/functions/polynomials/polcyclo0000644000175000017500000000160311636712103020020 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 can deal with all rational values $a$; otherwise it assumes that $a^d - 1$ is invertible for all $d\mid n$. If this is not the case, 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.5.5/src/functions/polynomials/polhermite0000644000175000017500000000102612141040641020334 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.5.5/src/functions/polynomials/polrootspadic0000644000175000017500000000141411636712103021056 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: row vector of $p$-adic roots of the polynomial \var{pol}, given to $p$-adic precision $r$. Multiple roots are \emph{not} repeated. $p$ is assumed to be a prime, and \var{pol} to be non-zero modulo $p$. 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$. If \var{pol} has inexact \typ{PADIC} coefficients, this is not always well-defined; in this case, the equation is first made integral, then lifted to $\Z$. Hence the roots given are approximations of the roots of a polynomial which is $p$-adically close to the input. pari-2.5.5/src/functions/polynomials/deriv0000644000175000017500000000152011636712103017303 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.5.5/src/functions/polynomials/poltchebi0000644000175000017500000000056512147140046020152 0ustar billbillFunction: poltchebi Section: polynomials C-Name: polchebyshev1 Prototype: LDn Help: poltchebi(n,{v=x}): Tchebitcheff polynomial of degree n, in variable v. (For backward compatibility.) Doc: creates the $n^{\text{th}}$ \idx{Chebyshev} polynomial~$T_n$ of the first kind in variable $v$. This function is retained for backward compatibility only. Use \tet{polchebyshev}. pari-2.5.5/src/functions/polynomials/subst0000644000175000017500000000205611636712103017337 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.5.5/src/functions/polynomials/polisirreducible0000644000175000017500000000071412147140046021535 0ustar billbillFunction: polisirreducible Section: polynomials C-Name: gisirreducible Prototype: G 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.5.5/src/functions/polynomials/pollead0000644000175000017500000000114111636712103017611 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.5.5/src/functions/polynomials/poldiscreduced0000644000175000017500000000102011636712103021156 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.5.5/src/functions/polynomials/padicfields0000644000175000017500000000345512147140046020451 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 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.5.5/src/functions/polynomials/polrecip0000644000175000017500000000036011636712103020010 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.5.5/src/functions/polynomials/polzagier0000644000175000017500000000131211636712103020165 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.5.5/src/functions/polynomials/poldisc0000644000175000017500000000074211636712103017634 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: (pol):gen discsr($1) (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. The algorithm used is the \idx{subresultant algorithm}. pari-2.5.5/src/functions/polynomials/polrootsmod0000644000175000017500000000151512147140046020556 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}. The particular non-prime value $p=4$ is accepted, mainly for $2$-adic computations. Multiple roots are \emph{not} repeated. \bprog ? polrootsmod(x^2-1,2) %1 = [Mod(1, 2)]~ ? polrootsmod(x^2-1,4) %2 = [Mod(1, 4), Mod(3, 4)]~ @eprog\noindent If $p$ is very small, you may set $\fl=1$, which uses a naive search. pari-2.5.5/src/functions/polynomials/polresultant0000644000175000017500000000223312147140046020727 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 = res(x,y)$, use the \tet{bezoutres} 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.5.5/src/functions/polynomials/polhensellift0000644000175000017500000000216011636712103021043 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)] ? lift(lift( r[1] * r[2] * Mod(Mod(1,p^6),T) )) %2 = x^2 + (t + 1) @eprog pari-2.5.5/src/functions/polynomials/intformal0000644000175000017500000000116412147140046020170 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 main variable if $v$ is omitted, with respect to the variable $v$ otherwise. Since PARI does not know about ``abstract'' logarithms (they are immediately evaluated, if only to a power series), logarithmic terms in the result will yield an error. $x$ can be of any type. When $x$ is a rational function, it is assumed that the base ring is an integral domain of characteristic zero. pari-2.5.5/src/functions/polynomials/polsylvestermatrix0000644000175000017500000000122011636712103022167 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.5.5/src/functions/polynomials/pollegendre0000644000175000017500000000071411636712103020476 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.5.5/src/functions/number_theoretical/0000755000175000017500000000000012212611624017553 5ustar billbillpari-2.5.5/src/functions/number_theoretical/sqrtint0000644000175000017500000000044411636712103021207 0ustar billbillFunction: sqrtint Section: number_theoretical C-Name: sqrtint Prototype: G Help: sqrtint(x): integer square root of x (x integer). Description: (gen):int sqrtint($1) Doc: integer square root of $x$, which must be a non-negative integer. The result is non-negative and rounded towards zero. pari-2.5.5/src/functions/number_theoretical/znlog0000644000175000017500000000334712147140046020640 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. If no o is given, assume that g generate (Z/nZ)*. Doc: discrete logarithm of $x$ in $(\Z/N\Z)^*$ in base $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$. If no $o$ is given, assume that $g$ generate $(\Z/N\Z)^*$. This function uses a simple-minded combination of generic discrete log algorithms (index calculus methods are not yet implemented). \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$ small), \item Pollard rho method ($q$ large). 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. \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 @eprog\noindent The result is undefined when $x$ is not a power of $g$ or when $x$ is not invertible mod $N$: \bprog ? znlog(6, Mod(2,3)) *** at top-level: znlog(6,Mod(2,3)) *** ^----------------- *** znlog: impossible inverse modulo: Mod(0, 3). @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.5.5/src/functions/number_theoretical/numdiv0000644000175000017500000000064412147140046021006 0ustar billbillFunction: numdiv Section: number_theoretical C-Name: gnumbdiv Prototype: G Help: numdiv(x): number of divisors of x. Description: (int):int numbdiv($1) (gen):gen gnumbdiv($1) Doc: number of divisors of $|x|$. $x$ must be of type integer. The function accepts vector/matrices arguments, and is then applied componentwise. Variant: If $x$ is a \typ{INT}, one may use \fun{GEN}{numbdiv}{GEN n} directly. pari-2.5.5/src/functions/number_theoretical/qfbred0000644000175000017500000000263211636712103020747 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.5.5/src/functions/number_theoretical/bigomega0000644000175000017500000000117012147140046021251 0ustar billbillFunction: bigomega Section: number_theoretical C-Name: gbigomega Prototype: G Help: bigomega(x): number of prime divisors of x, counted with multiplicity. Description: (int):small bigomega($1) (gen):gen gbigomega($1) 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 The function accepts vector/matrices arguments, and is then applied componentwise. Variant: For a \typ{INT} $x$, the variant \fun{long}{bigomega}{GEN n} is generally easier to use. pari-2.5.5/src/functions/number_theoretical/gcd0000644000175000017500000000437711636712103020251 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) %2 = 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{bezout}, 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.5.5/src/functions/number_theoretical/fflog0000644000175000017500000000226412147140046020601 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$. 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. See \tet{znlog} for the limitations of the underlying discrete log algorithms. \bprog ? t = ffgen(ffinit(7,5)); ? o = fforder(t) %2 = 5602 \\@com \emph{not} a primitive root. ? fflog(t^10,t) %3 = 11214 \\@com Actually correct modulo o. We are lucky ! ? 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 \\ no surprise there ! ? fforder(g^10000, g, o) ? fflog(g^10000, g, o) %9 = 10000 @eprog pari-2.5.5/src/functions/number_theoretical/prime0000644000175000017500000000032312147140046020612 0ustar billbillFunction: prime Section: number_theoretical C-Name: prime Prototype: L Help: prime(n): returns the n-th prime (n C-integer). Doc: the $x^{\text{th}}$ prime number, which must be among the precalculated primes. pari-2.5.5/src/functions/number_theoretical/primepi0000644000175000017500000000053112147140046021144 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$. Uses a naive algorithm so that $x$ must be less than \kbd{primelimit}. pari-2.5.5/src/functions/number_theoretical/divisors0000644000175000017500000000116311636712103021344 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.5.5/src/functions/number_theoretical/bezoutres0000644000175000017500000000070112147140046021520 0ustar billbillFunction: bezoutres Section: number_theoretical C-Name: vecbezoutres Prototype: GG Help: bezoutres(x,y): gives a 3-dimensional row vector [u,v,d] such that d=resultant(x,y) and u*x+v*y=d, where x and y are polynomials. Doc: finds $u$ and $v$ such that $x*u + y*v = d$, where $d$ is the resultant of $x$ and $y$. The result is the row vector $[u,v,d]$. \sidx{extended gcd} The algorithm used (subresultant) assumes that the base ring is a domain. pari-2.5.5/src/functions/number_theoretical/bezout0000644000175000017500000000171412147140046021013 0ustar billbillFunction: bezout Section: number_theoretical C-Name: vecbezout Prototype: GG Help: bezout(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} 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 ? bezout(a,a) %2 = [0, 1, x + 0.E-28] ? bezout(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.5.5/src/functions/number_theoretical/partitions0000644000175000017500000000163411636712103021701 0ustar billbillFunction: partitions Section: number_theoretical C-Name: partitions Prototype: LD0,L, Help: partitions(n,{restr=0}): return vector of partitions of n, a positive integer. The second optional argument may be set to a number smaller than n to restrict the value of each element in the partitions to that value. The default of 0 means that this maximum is n itself. Doc: returns vector of partitions of the integer $n$ (negative values return \kbd{[]}, $n = 0$ returns the trivial partition of the empty set). The second optional argument may be set to a non-negative number smaller than $n$ to restrict the value of each element in the partitions to that value. The default of 0 means that this maximum is $n$ itself. A partition is given by a \typ{VECSMALL}: \bprog ? partitions(4, 2) %1 = [Vecsmall([2, 2]), Vecsmall([1, 1, 2]), Vecsmall([1, 1, 1, 1])] @eprog\noindent correspond to $2+2$, $1+1+2$, $1+1+1+1$. pari-2.5.5/src/functions/number_theoretical/qfbpowraw0000644000175000017500000000052211636712103021510 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.5.5/src/functions/number_theoretical/eulerphi0000644000175000017500000000102312147140046021311 0ustar billbillFunction: eulerphi Section: number_theoretical C-Name: geulerphi Prototype: G Help: eulerphi(x): Euler's totient function of x. Description: (int):int eulerphi($1) (gen):gen geulerphi($1) Doc: Euler's $\phi$ (totient)\sidx{Euler totient function} function of $|x|$, in other words $|(\Z/x\Z)^*|$. Normally, $x$ must be of type integer, but the function accepts vector/matrices arguments, and is then applied componentwise. Variant: For a \typ{INT} $x$, the variant \fun{GEN}{eulerphi}{GEN n} is also available. pari-2.5.5/src/functions/number_theoretical/znprimroot0000644000175000017500000000166012147140046021726 0ustar billbillFunction: znprimroot Section: number_theoretical C-Name: znprimroot0 Prototype: G Help: znprimroot(n): returns a primitive root of n when it exists. Description: (int):gen znprimroot($1) (gen):gen znprimroot0($1) 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, then the smallest positive primitive root is returned. This is no longer true for composites. 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 very costly if $p$ is large. The function accepts vector/matrices arguments, and is then applied componentwise. Variant: For a \typ{INT} $x$, the special case \fun{GEN}{znprimroot}{GEN n} is also available. pari-2.5.5/src/functions/number_theoretical/hilbert0000644000175000017500000000103011636712103021124 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.5.5/src/functions/number_theoretical/factorff0000644000175000017500000000304011636712103021270 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.5.5/src/functions/number_theoretical/factorback0000644000175000017500000000235611636712103021606 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.5.5/src/functions/number_theoretical/contfrac0000644000175000017500000000556411636712103021312 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.5.5/src/functions/number_theoretical/ispower0000644000175000017500000000230511636712103021171 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.5.5/src/functions/number_theoretical/primes0000644000175000017500000000065312147140046021003 0ustar billbillFunction: primes Section: number_theoretical C-Name: primes Prototype: L Help: primes(x): returns the vector of the first x primes. Doc: creates a row vector whose components are the first $x$ prime numbers, which must be among the precalculated primes. \bprog ? primes(10) \\ the first 10 primes %1 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] ? primes(primepi(10)) \\ the primes up to 10 %2 = [2, 3, 5, 7] @eprog pari-2.5.5/src/functions/number_theoretical/polrootsff0000644000175000017500000000230311636712103021674 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.5.5/src/functions/number_theoretical/qfbnucomp0000644000175000017500000000160611636712103021476 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.5.5/src/functions/number_theoretical/quadunit0000644000175000017500000000107711636712103021340 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.5.5/src/functions/number_theoretical/qfbnupow0000644000175000017500000000056011636712103021343 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.5.5/src/functions/number_theoretical/kronecker0000644000175000017500000000144012147140046021462 0ustar billbillFunction: kronecker Section: number_theoretical C-Name: gkronecker Prototype: GG 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) (int, int):small kronecker($1, $2) (gen, gen):gen gkronecker($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.5.5/src/functions/number_theoretical/addprimes0000644000175000017500000000135511636712103021455 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.5.5/src/functions/number_theoretical/stirling0000644000175000017500000000247011636712103021337 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]; 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.5.5/src/functions/number_theoretical/quadpoly0000644000175000017500000000064612147140046021344 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.5.5/src/functions/number_theoretical/ffgen0000644000175000017500000000103112147140046020560 0ustar billbillFunction: ffgen Section: number_theoretical C-Name: ffgen Prototype: GDn Help: ffgen(P,{v}): return the generator g=X mod P(X) of the finite field defined by the polynomial P(X). If v is given, the variable name is used to display g, else the variable of the polynomial P is used. Doc: return the generator $g=X \pmod{P(X)}$ of the finite field defined by the polynomial $P$ (which must have \typ{INTMOD} coefficients). If \kbd{v} is given, the variable name is used to display $g$, else the variable of the polynomial $P$ is used. pari-2.5.5/src/functions/number_theoretical/bestappr0000644000175000017500000000527612147140046021332 0ustar billbillFunction: bestappr Section: number_theoretical C-Name: bestappr0 Prototype: GDGDG Help: bestappr(x, {A},{B}): if x is real, gives the best approximation to x with denominator less or equal to A. If x is an intmod, returns a rational number congruent to x with numerator less than A and denominator less than B, which must be given. If x is a polmod, returns a rational functions congruent to x with numerator degree less than A and denominator degree less than B, which must be given. Otherwise applies recursively to all components. Doc: if $B$ is omitted, finds the best rational approximation to $x\in\R$ using continued fractions. If $A$ is omitted, return the best approximation affordable given the input accuracy; otherwise make sure that denominator is at most equal to $A$. If $B$ is present perform rational modular reconstruction (see below). In both cases, the function applies recursively to components of complex objects (polynomials, vectors, \dots). \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, $n/d$ is the best rational approximation to $x$ if $|d x - n| < |v x - u|$ for all integers $(u,v)$ with $v \leq A$. (Which implies that $n/d$ is a convergent of the continued fraction of $x$.) If $x$ is an \typ{INTMOD}, (or a recursive combination of those), modulo $N$ say, $B$ must be present. The routine then returns the unique rational number $a/b$ in coprime integers $a\leq A$ and $b\leq B$ which is congruent to $x$ modulo $N$. If $N \leq 2AB$, uniqueness is not guaranteed and the function fails with an error message. If rational reconstruction is not possible (no such $a/b$ exists for at least one component of $x$), returns $-1$. \bprog ? bestappr(Mod(18526731858, 11^10), 10^10, 10^10) *** at top-level: bestappr(Mod(1852673 *** ^-------------------- *** bestappr: ratlift: must have 2*amax*bmax < m, found amax=10000000000 bmax=10000000000 m=25937424601 ? bestappr(Mod(18526731858, 11^10), 10^5, 10^5) %1 = 1/7 ? bestappr(Mod(18526731858, 11^20), 10^10, 10^10) %2 = -1 @eprog\noindent In most concrete uses, $B$ is a prime power and we performed Hensel lifting to obtain $x$. If $x$ is a \typ{POLMOD}, modulo $T$ say, $B$ must be present. The routine then returns the unique rational function $P/Q$ with $\deg P\leq A$ and $\deg Q\leq B$ which is congruent to $x$ modulo $T$. If $\deg T \leq A+B$, uniqueness is not guaranteed and the function fails with an error message. If rational reconstruction is not possible, returns $-1$. Variant: Also available is \fun{GEN}{bestappr}{GEN x, GEN A}. pari-2.5.5/src/functions/number_theoretical/omega0000644000175000017500000000114512147140046020571 0ustar billbillFunction: omega Section: number_theoretical C-Name: gomega Prototype: G Help: omega(x): number of distinct prime divisors of x. Description: (int):small omega($1) (gen):gen gomega($1) 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 The function accepts vector/matrices arguments, and is then applied componentwise. Variant: For a \typ{INT} $x$, the variant \fun{long}{omega}{GEN n} is generally easier to use. pari-2.5.5/src/functions/number_theoretical/dirmul0000644000175000017500000000126112200714053020767 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.5.5/src/functions/number_theoretical/qfbclassno0000644000175000017500000000477111636712103021645 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.5.5/src/functions/number_theoretical/quadgen0000644000175000017500000000067511636712103021135 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.5.5/src/functions/number_theoretical/zncoppersmith0000644000175000017500000000430312147140046022405 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 p = nextprime(random(10^30)); q = nextprime(random(10^30)); N = p*q; p0 = p % 10^20; \\ assume we know 1) p > 10^29, 2) the last 19 digits of p p1 = zncoppersmith(10^19*x + p0, N, 10^12, 10^29) \\ result in 10ms. %1 = [35023733690] ? gcd(p1[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 3.8s. %3 = [265174753892462432] ? %[1] == x0 %4 = 1 @eprog\noindent We guessed an integer of the order of $10^{18}$ in a couple of seconds. pari-2.5.5/src/functions/number_theoretical/qfbsolve0000644000175000017500000000162411636712103021325 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.5.5/src/functions/number_theoretical/nextprime0000644000175000017500000000124412147140046021514 0ustar billbillFunction: nextprime Section: number_theoretical C-Name: gnextprime Prototype: G Help: nextprime(x): smallest pseudoprime >= x. Description: (int):int nextprime($1) (gen):gen gnextprime($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}. The function accepts vector/matrices arguments, and is then applied componentwise. Variant: For a scalar $x$, \fun{long}{nextprime}{GEN n} is also available. pari-2.5.5/src/functions/number_theoretical/binomial0000644000175000017500000000101611636712103021271 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.5.5/src/functions/number_theoretical/removeprimes0000644000175000017500000000073411636712103022222 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.5.5/src/functions/number_theoretical/qfbhclassno0000644000175000017500000000052311636712103022004 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.5.5/src/functions/number_theoretical/sumdedekind0000644000175000017500000000051411636712103021775 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.5.5/src/functions/number_theoretical/moebius0000644000175000017500000000070012147140046021140 0ustar billbillFunction: moebius Section: number_theoretical C-Name: gmoebius Prototype: G Help: moebius(x): Moebius function of x. Description: (int):small moebius($1) (gen):gen gmoebius($1) Doc: \idx{Moebius} $\mu$-function of $|x|$. $x$ must be of type integer. The function accepts vector/matrices arguments, and is then applied componentwise. Variant: For a \typ{INT} $x$, the variant \fun{long}{moebius}{GEN n} is generally easier to use. pari-2.5.5/src/functions/number_theoretical/quadray0000644000175000017500000000114411636712103021147 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.5.5/src/functions/number_theoretical/core0000644000175000017500000000122511636712103020431 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.5.5/src/functions/number_theoretical/znstar0000644000175000017500000000130311636712103021017 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$. pari-2.5.5/src/functions/number_theoretical/numbpart0000644000175000017500000000101411636712103021325 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.5.5/src/functions/number_theoretical/issquarefree0000644000175000017500000000104212147140046022173 0ustar billbillFunction: issquarefree Section: number_theoretical C-Name: gissquarefree Prototype: G Help: issquarefree(x): true(1) if x is squarefree, false(0) if not. Description: (int):bool issquarefree($1) (gen):gen gissquarefree($1) Doc: true (1) if $x$ is squarefree, false (0) if not. Here $x$ can be an integer or a polynomial. The function accepts vector/matrices arguments, and is then applied componentwise. Variant: For scalar arguments $x$ (\typ{INT} or \typ{POL}), the function \fun{long}{issquarefree}{GEN x} is easier to use. pari-2.5.5/src/functions/number_theoretical/isfundamental0000644000175000017500000000071712147140046022337 0ustar billbillFunction: isfundamental Section: number_theoretical C-Name: gisfundamental Prototype: G Help: isfundamental(x): true(1) if x is a fundamental discriminant (including 1), false(0) if not. Description: (int):bool Z_isfundamental($1) (gen):gen gisfundamental($1) Doc: true (1) if $x$ is equal to 1 or to the discriminant of a quadratic field, false (0) otherwise. The function accepts vector/matrices arguments, and is then applied componentwise. pari-2.5.5/src/functions/number_theoretical/quadclassunit0000644000175000017500000000545412147140046022370 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 positive 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 = 0.2$ means that relations are easier to find, but more relations are needed and the linear algebra will be harder. 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.5.5/src/functions/number_theoretical/chinese0000644000175000017500000000204211636712103021115 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. This function also allows vector and matrix arguments, in which case the operation is recursively applied to each component of the vector or matrix. For polynomial arguments, it is applied to each coefficient. 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.5.5/src/functions/number_theoretical/fibonacci0000644000175000017500000000026011636712103021414 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.5.5/src/functions/number_theoretical/factor0000644000175000017500000001166412147140046020766 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 (up to primelimit if lim=0). 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 10^{15}$ (whose norm is $\leq 10^{15}$ 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 and satisfy $\var{lim} \leq \kbd{primelimit} + 1$; setting $\var{lim}=0$ is the same as setting it to $\kbd{primelimit} + 1$. 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 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] ? default(primelimit,10^9) time = 4,360 ms. %5 = 1000000000 ? factor(F, 10^9) \\ very slow time = 6,120 ms. %6 = [1009 1] [100003 1] [340282366920938463463374607431768211457 1] ? factorint(F, 1+8) \\ much faster, all small primes were found time = 40 ms. %7 = [1009 1] [100003 1] [340282366920938463463374607431768211457 1] ? factorint(F) \\ complete factorisation time = 260 ms. %8 = [1009 1] [100003 1] [59649589127497217 1] [5704689200685129054721 1] @eprog \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. 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 you want 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). 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 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, long 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.5.5/src/functions/number_theoretical/qfbcompraw0000644000175000017500000000054411636712103021645 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. pari-2.5.5/src/functions/number_theoretical/content0000644000175000017500000000200711636712103021152 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.5.5/src/functions/number_theoretical/coredisc0000644000175000017500000000215111636712103021273 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.5.5/src/functions/number_theoretical/fforder0000644000175000017500000000153512147140046021133 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.5.5/src/functions/number_theoretical/quaddisc0000644000175000017500000000033111636712103021273 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.5.5/src/functions/number_theoretical/znorder0000644000175000017500000000140111636712103021160 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.5.5/src/functions/number_theoretical/ffprimroot0000644000175000017500000000214011636712103021665 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.5.5/src/functions/number_theoretical/ispseudoprime0000644000175000017500000000303211636712103022367 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):bool 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.5.5/src/functions/number_theoretical/factorint0000644000175000017500000000404211636712103021472 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.5.5/src/functions/number_theoretical/quadregulator0000644000175000017500000000057011636712103022362 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.5.5/src/functions/number_theoretical/sigma0000644000175000017500000000147412147140046020606 0ustar billbillFunction: sigma Section: number_theoretical C-Name: gsumdivk 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: (int, ?1):int sumdiv($1) (int, 0):int numbdiv($1) (gen, ?1):gen gsumdiv($1) (gen, 0):gen gnumbdiv($1) (int, small):int sumdivk($1, $2) (gen, small):gen gsumdivk($1, $2) Doc: sum of the $k^{\text{th}}$ powers of the positive divisors of $|x|$. $x$ and $k$ must be of type integer. The function accepts vector/matrices arguments for $x$, and is then applied componentwise. Variant: Also available are \fun{GEN}{gsumdiv}{GEN n} ($k = 1$), \fun{GEN}{sumdivk}{GEN n,long k} ($n$ a \typ{INT}) and \fun{GEN}{sumdiv}{GEN n} ($k = 1$, $n$ a \typ{INT}) pari-2.5.5/src/functions/number_theoretical/contfracpnqn0000644000175000017500000000133412147140046022175 0ustar billbillFunction: contfracpnqn Section: number_theoretical C-Name: pnqn Prototype: G Help: contfracpnqn(x): [p_n,p_{n-1}; q_n,q_{n-1}] corresponding to the continued fraction x. 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$. pari-2.5.5/src/functions/number_theoretical/lcm0000644000175000017500000000264611636712103020264 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.5.5/src/functions/number_theoretical/dirdiv0000644000175000017500000000051611636712103020764 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.5.5/src/functions/number_theoretical/issquare0000644000175000017500000000303412147140046021334 0ustar billbillFunction: issquare Section: number_theoretical C-Name: gissquareall Prototype: GD& 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) (mp):int gissquare($1) (gen):gen gissquare($1) (int, &int):bool Z_issquarerem($1, &$2) (gen, &gen):gen gissquareall($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 ? issquare([4, x^2], &n) %3 = [1, 1] \\ both are squares ? n %4 = [2, x] \\ the square roots @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 function accepts vector/matrices arguments, and is then applied componentwise. Variant: Also available is \fun{GEN}{gissquare}{GEN x}. pari-2.5.5/src/functions/number_theoretical/ffinit0000644000175000017500000000106612147140046020762 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-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,g)}. pari-2.5.5/src/functions/number_theoretical/factorcantor0000644000175000017500000000133111636712103022164 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.5.5/src/functions/number_theoretical/direuler0000644000175000017500000000220112147140046021306 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,gen,?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.5.5/src/functions/number_theoretical/quadhilbert0000644000175000017500000000110111636712103021776 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.5.5/src/functions/number_theoretical/precprime0000644000175000017500000000126312147140046021470 0ustar billbillFunction: precprime Section: number_theoretical C-Name: gprecprime Prototype: G Help: precprime(x): largest pseudoprime <= x, 0 if x<=1. Description: (int):int precprime($1) (gen):gen gprecprime($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}. The function accepts vector/matrices arguments, and is then applied componentwise. Variant: For a scalar $x$, \fun{long}{precprime}{GEN n} is also available. pari-2.5.5/src/functions/number_theoretical/factormod0000644000175000017500000000145511636712103021464 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.5.5/src/functions/number_theoretical/factorial0000644000175000017500000000053311636712103021446 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.5.5/src/functions/number_theoretical/qfbprimeform0000644000175000017500000000117711636712103022200 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.5.5/src/functions/number_theoretical/isprime0000644000175000017500000000512611636712103021155 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) (int, 1):bool plisprime($1, 0) (int, 2):gen plisprime($1, 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.5.5/src/headers/0000755000175000017500000000000012212611624013303 5ustar billbillpari-2.5.5/src/headers/pariold.h0000644000175000017500000002601312147140046015112 0ustar billbill/* $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. */ /* For compatibility with 1.x.x */ /*functions renamed*/ #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 isfundamental Z_isfundamental #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) apell(e,p) #define apell2(e,p) apell(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)gach #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)gash #define lasin (long)gasin #define lassmat (long)matcompanion #define latan (long)gatan #define lath (long)gath #define lbezout (long)bezout #define lbinome (long)binomial #define lcaract (long)caract #define lcaradj (long)caradj #define lceil (long)gceil #define lch (long)gch #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)ggamd #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)mpexp1 #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)gsh #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)gth #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.5.5/src/headers/paricom.h0000644000175000017500000000677112147140046015123 0ustar billbill/* $Id$ 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) /*=====================================================================*/ /* CATCH(numer) { * recovery * } TRY { * code * } ENDCATCH * will execute 'code', then 'recovery' if exception 'numer' is thrown * [ any exception if numer == CATCH_ALL ]. * RETRY = as TRY, but execute 'recovery', then 'code' again [still catching] */ #define CATCH(err) { \ VOLATILE long __err = err, __catcherr = -1; \ int pari_errno; \ jmp_buf __env; \ if ((pari_errno = setjmp(__env))) #define RETRY else __catcherr = err_catch(__err, &__env); { #define TRY else { __catcherr = err_catch(__err, &__env); #define CATCH_RELEASE() err_leave(__catcherr) #define ENDCATCH } CATCH_RELEASE(); } extern const long CATCH_ALL; 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 THREAD GEN bernzone; extern GEN primetab; extern GEN gen_m1,gen_1,gen_2,gen_m2,ghalf,gen_0,gnil; extern VOLATILE THREAD int PARI_SIGINT_block, PARI_SIGINT_pending; extern const long lontyp[]; extern THREAD void* global_err_data; 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_err_recover)(long); 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 }; #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 bern(i) (bernzone + 3 + (i)*bernzone[2]) #define ONLY_REM ((GEN*)0x1L) #define ONLY_DIVIDES ((GEN*)0x2L) #define DIFFPTR_SKIP 255 /* Skip these entries */ #define NEXT_PRIME_VIADIFF(p,d) STMT_START \ { while (*(d) == DIFFPTR_SKIP) (p) += *(d)++; (p) += *(d)++; } STMT_END #define NEXT_PRIME_VIADIFF_CHECK(p,d) STMT_START \ { if (!*(d)) pari_err(primer1,0); NEXT_PRIME_VIADIFF(p,d); } STMT_END pari-2.5.5/src/headers/parinf.h0000644000175000017500000001425412147140046014743 0ustar billbill/* $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 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_RNF }; /* idealtyp */ enum { id_PRINCIPAL = 0, id_PRIME, id_MAT }; typedef struct { GEN x; /* defining polynomial (monic, 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 index; /* [O_K : Z[X]/(x)] */ GEN lead; /* leading coeff of initial polynomial defining K if non monic */ GEN dx; /* disc(x) */ GEN basden; /* [nums(bas), dens(bas)] */ } nfbasic_t; typedef struct { GEN dT; /* discriminant of defining polynomial */ 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; /* 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 (*cmp)(GEN, GEN); int (*equal1)(GEN); }; /* 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_obj(GEN S, long tag, GEN (*build)(GEN)); GEN check_and_build_cycgen(GEN bnf); double check_bach(double cbach, double B); 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 eltabstorel(GEN x, GEN T, GEN pol, GEN k); GEN eltreltoabs(GEN rnfeq, GEN x); 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); long int_elt_val(GEN nf, GEN x, GEN p, GEN bp, GEN *t); 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 norm_by_embed(long r1, GEN x); 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 special_anti_uniformizer(GEN nf, GEN pr); GEN subgroupcondlist(GEN cyc, GEN bound, GEN listKer); GEN T2_from_embed_norm(GEN x, long r1); 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.5.5/src/headers/parigen.h0000644000175000017500000001251312147140046015105 0ustar billbill/* $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. */ /* This file defines the parameters of the GEN type */ typedef long *GEN; typedef unsigned long pari_ulong; #define ulong pari_ulong #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 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 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 }; pari-2.5.5/src/headers/paripriv.h0000644000175000017500000005144512147140046015323 0ustar billbill/* $Id$ 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 *); /* for (ulong*) GENs */ typedef ulong *uGEN; #define ucoeff(a,i,j) (((uGEN*)(a))[j][i]) #define ugel(a,i) ((uGEN*)(a))[i] /* 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); /* generic */ GEN trans_fix_arg(long *prec, GEN *s0, GEN *sig, pari_sp *av, GEN *res); GEN transc(GEN (*f) (GEN, long), GEN x, long prec); 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 */ 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 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 gstore(GEN *x, GEN y); 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); GEN divsum(GEN num, 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); 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 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 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); /* 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 logagmcx(GEN q, long prec); 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); int OK_bern(long nb, long prec); /* 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); ulong usqrtsafe(ulong a); /* 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 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); INLINE void rowselect_p(GEN A, GEN B, GEN p, long init); 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, byteptr d); GEN mpqs(GEN N); ulong gcduodd(ulong x, ulong y); long Z_lvalrem_stop(GEN n, ulong p, int *stop); long u_lvalrem_stop(ulong *n, ulong p, int *stop); /* 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); GEN Kronecker_to_FpXQX(GEN z, GEN pol, GEN p); GEN FpX_quad_root(GEN x, GEN p, int unknown); long FpX_split_Berlekamp(GEN *t, GEN pp); GEN FqX_split_all(GEN z, GEN T, GEN p); long FqX_split_by_degree(GEN *pz, GEN u, GEN q, GEN T, GEN p); long FqX_split_deg1(GEN *pz, GEN u, GEN q, 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_intern0(GEN x,long v); #define lift_intern(x) (lift_intern0((x),-1)) /* 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 field */ enum { t_FF_FpXQ = 0, t_FF_Flxq = 1, t_FF_F2xq = 2 }; /* for Buchall_param */ enum { fupb_NONE, fupb_RELAT, fupb_LARGE, fupb_PRECI }; /* Allocation / gerepile */ void debug_stack(void); void fill_stack(void); void init_dalloc(void); double *dalloc(size_t n); INLINE void gerepilecoeffs2(pari_sp av, GEN x, int n, GEN y, int o); 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.) */ 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 init80col(void); int pari_kernel_init(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 *res; /* 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 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); void evalstate_save(struct pari_evalstate *state); void debug_context(void); /* GP_DATA */ typedef struct { gp_hist *hist; gp_pp *pp; gp_path *path; pariout_t *fmt; ulong lim_lines, flags; int echo, breakloop, recover, use_readline; /* GP-specific */ int secure, simplify, strictmatch, chrono; /* libpari ? */ pari_timer *T; long last_time; /* duration of last interactive gp command */ } gp_data; extern gp_data *GP_DATA; /* GP_DATA->flags */ enum { gpd_QUIET=1, gpd_TEST=2, gpd_EMACS=256, gpd_TEXMACS=512}; /* 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); 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 */ /* Flx.c */ GEN FlxX_recipspec(GEN x, long l, long n, long vs); GEN FlxX_sub(GEN x, GEN y, ulong p); GEN FlxX_subspec(GEN x, GEN y, ulong p, long lx, long ly); GEN FlxX_swap(GEN x, long n, long ws); GEN zxX_to_Kronecker(GEN P, GEN Q); GEN zxX_to_Kronecker_spec(GEN P, long lp, GEN Q); GEN Flx_addshift(GEN x, GEN y, ulong p, long d); GEN Flx_addspec(GEN x, GEN y, ulong p, long lx, long ly); GEN Flx_even_odd_comb(GEN P, ulong u, ulong v, ulong p); GEN Flx_mulspec(GEN a, GEN b, ulong p, long na, long nb); GEN Flx_negspec(GEN x, ulong p, long l); GEN Flx_recipspec(GEN x, long l, long n); GEN Flx_sqrspec(GEN a, ulong p, long na); GEN Flx_subspec(GEN x, GEN y, ulong p, long lx, long ly); GEN Kronecker_to_FlxqX(GEN z, GEN T, ulong p); GEN FlxqX_invMontgomery(GEN T, GEN Q, ulong p); GEN FlxqX_mulspec(GEN x, GEN y, GEN T, ulong p, long lx, long ly); GEN FlxqX_rem_Montgomery(GEN x, GEN mg, GEN T, GEN Q, ulong p); /* Qfb.c */ GEN redimagsl2(GEN q, GEN *U); GEN redrealsl2(GEN V); GEN redrealsl2step(GEN A); GEN redtausl2(GEN t, GEN *U); /* alglin1.c */ typedef long (*pivot_fun)(GEN,GEN,long,GEN); GEN RgM_pivots(GEN x0, GEN data, long *rr, pivot_fun pivot); INLINE void vecselect_p(GEN A, GEN B, GEN p, long init, long lB); /* arith1.c */ GEN bestappr_mod(GEN x, GEN A, GEN B); 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 */ byteptr initprimes0(ulong maxnum, long *lenp, ulong *lastp); long set_optimize(long what, GEN g); /* base1.c */ GEN nffromhnfbasis(GEN nf, GEN x); GEN nftohnfbasis(GEN nf, GEN x); /* base2.c */ GEN gen_if_principal(GEN bnf, GEN x); int nfissquarefree(GEN nf, GEN x); GEN nfreducemodpr_i(GEN x, GEN prh); GEN polsymmodp(GEN g, GEN p); /* base3.c */ void check_nfelt(GEN x, GEN *den); 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); GEN checkrnfeq(GEN x); /* bibli1.c */ GEN plindep(GEN x); GEN pslq(GEN x); GEN pslqL2(GEN x); /* buch1.c */ GEN form_to_ideal(GEN x); GEN qfbforms(GEN D); /* buch2.c */ typedef struct GRHcheck_t { double cD, cN; long checkok; } GRHcheck_t; void init_GRHcheck(GRHcheck_t *S, long N, long R1, double LOGD); 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); /* elliptic.c */ GEN weipell0(GEN e, long prec, long PREC); /* 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_files(void); void pari_close_files(void); int popinfile(void); GEN readobj(FILE *f, int *ptc); pariFILE* try_pipe(const char *cmd, int flag); void writeGEN(GEN x, FILE *f); void writenamedGEN(GEN x, const char *s, FILE *f); /* galconj.c */ GEN galoiscosets(GEN O, GEN perm); long intheadlong(GEN x, GEN mod); long isomborne(GEN P, GEN den, GEN p); 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); int uisprime_nosmalldiv(ulong n); /* init.c */ void err_recover(long numerr); 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 FpX_factcantor(GEN f, GEN pp, long flag); GEN FqX_Berlekamp_ker(GEN u, GEN T, GEN q, GEN p); GEN FqX_rand(long d1, long v, GEN T, GEN p); long FqX_split_Berlekamp(GEN *t, GEN q, GEN T, GEN p); GEN Zp_appr(GEN f, GEN a); int cmp_padic(GEN x, GEN y); GEN factcantor0(GEN f, GEN pp, long flag); GEN trivfact(void); /* polarit2.c */ GEN sylvestermatrix_i(GEN x, GEN y); /* QX_factor */ GEN DDF_roots(GEN pol, GEN polp, GEN p); void factor_quad(GEN x, GEN res, long *ptcnt); long logint(GEN B, GEN y, GEN *ptq); /* 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); byteptr init_modular(ulong *p); 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 */ void pari_init_floats(void); void pari_close_floats(void); GEN rootsof1complex(GEN n, long prec); GEN rootsof1padic(GEN n, GEN y); /* 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 twistpartialzeta(GEN q, long f, long c, GEN va, GEN cff); ENDEXTERN pari-2.5.5/src/headers/pariinl.h0000644000175000017500000015155312147140046015126 0ustar billbill/* $Id$ 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 */ /* */ /*******************************************************************/ INLINE GEN mkintmod(GEN x, GEN y) { GEN v = cgetg(3, t_INTMOD); gel(v,1) = y; gel(v,2) = x; return v; } 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) { GEN v = cgetg(3, t_POLMOD); gel(v,1) = y; gel(v,2) = x; return v; } INLINE GEN mkfrac(GEN x, GEN y) { GEN v = cgetg(3, t_FRAC); gel(v,1) = x; gel(v,2) = y; return v; } INLINE GEN mkfraccopy(GEN x, GEN y) { GEN v = cgetg(3, t_FRAC); gel(v,1) = icopy(x); gel(v,2) = icopy(y); return v; } 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 mkcomplex(GEN x, GEN y) { GEN v = cgetg(3, t_COMPLEX); gel(v,1) = x; gel(v,2) = y; return v; } INLINE GEN gen_I(void) { return mkcomplex(gen_0, gen_1); } INLINE GEN cgetc(long l) { GEN u = cgetg(3,t_COMPLEX); gel(u,1) = cgetr(l); gel(u,2) = cgetr(l); return u; } 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; } /* vec */ INLINE GEN mkvec(GEN x) { GEN v = cgetg(2, t_VEC); gel(v,1) = x; return v; } INLINE GEN mkvec2(GEN x, GEN y) { GEN v = cgetg(3,t_VEC); gel(v,1) = x; gel(v,2) = y; return v; } INLINE GEN mkvec3(GEN x, GEN y, GEN z) { GEN v=cgetg(4,t_VEC); gel(v,1) = x; gel(v,2) = y; gel(v,3) = z; return v; } INLINE GEN mkvec4(GEN x, GEN y, GEN z, GEN t) { GEN v=cgetg(5,t_VEC); gel(v,1) = x; gel(v,2) = y; gel(v,3) = z; gel(v,4) = t; return v; } INLINE GEN mkvec5(GEN x, GEN y, GEN z, GEN t, GEN u) { 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; } INLINE GEN mkvecs(long x) { GEN v = cgetg(2, t_VEC); gel(v,1) = stoi(x); return v; } INLINE GEN mkvec2s(long x, long y) { GEN v = cgetg(3,t_VEC); gel(v,1) = stoi(x); gel(v,2) = stoi(y); return v; } INLINE GEN mkvec3s(long x, long y, long z) { GEN v=cgetg(4,t_VEC); gel(v,1)=stoi(x); gel(v,2)=stoi(y); gel(v,3)=stoi(z); return v; } 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) { GEN v = cgetg(2, t_COL); gel(v,1) = x; return v; } INLINE GEN mkcol2(GEN x, GEN y) { GEN v = cgetg(3,t_COL); gel(v,1) = x; gel(v,2) = y; return v; } INLINE GEN mkcolcopy(GEN x) { GEN v = cgetg(2, t_COL); gel(v,1) = gcopy(x); return v; } /* mat */ INLINE GEN mkmat(GEN x) { GEN v = cgetg(2, t_MAT); gel(v,1) = x; return v; } INLINE GEN mkmat2(GEN x, GEN y) { GEN v=cgetg(3,t_MAT); gel(v,1)=x; gel(v,2)=y; return v; } INLINE GEN mkmatcopy(GEN x) { GEN v = cgetg(2, t_MAT); gel(v,1) = gcopy(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; } INLINE GEN const_vec(long n, GEN x) { GEN v = cgetg(n+1, t_VEC); long i; for (i = 1; i <= n; i++) gel(v,i) = x; return v; } INLINE GEN const_col(long n, GEN x) { GEN v = cgetg(n+1, t_COL); long i; for (i = 1; i <= n; i++) gel(v,i) = x; return v; } 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; } /* 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 = const_vecsmall(l+1, 0); 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 vecsmall_ei(long n, long i) { GEN e = const_vecsmall(n,0); 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 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++) V[i] = 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[i]; return t; } INLINE long vecsmall_min(GEN x) { long i, 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 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_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 RgM_is_ZM(GEN x) { long i, j, h, l = lg(x); if (l == 1) return 1; h = lg(gel(x,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; } /********************************************************************/ /** **/ /** Dynamic arrays implementation **/ /** **/ /********************************************************************/ INLINE void ** stack_base(pari_stack *s) { return (void **) ((ulong)s + (ulong)s->offset); } INLINE void stack_init(pari_stack *s, size_t size, void **data) { s->offset = (ulong)data-(ulong)s; *data = NULL; s->n = 0; s->alloc = 0; s->size = size; } INLINE void stack_alloc(pari_stack *s, long nb) { void **sdat = 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 stack_new(pari_stack *s) { stack_alloc(s, 1); return s->n++; } INLINE void stack_delete(pari_stack *s) { void **sdat = stack_base(s); if (*sdat) free(*sdat); } INLINE void stack_pushp(pari_stack *s, void *u) { long n = stack_new(s); void **sdat =(void**) *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) q[lx] = x[lx]; q[0] = evaltyp(t_INT)|evallg(lq); return q; } 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) { GENbin *p = copy_bin(x); avma = av; return bin_copy(p); } /* 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(typeer,"cxcompotor"); return NULL; /* not reached */ } } INLINE GEN cxtofp(GEN x, long prec) { GEN z = cgetg(3,t_COMPLEX); gel(z,1) = cxcompotor(gel(x,1),prec); gel(z,2) = cxcompotor(gel(x,2),prec); return z; } INLINE double gtodouble(GEN x) { if (typ(x)!=t_REAL) { pari_sp av = avma; x = gtofp(x, DEFAULTPREC); avma = av; } return rtodbl(x); } INLINE long gtos(GEN x) { if (typ(x) != t_INT) pari_err(talker,"gtos expected an integer, got '%Ps'",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 Q_abs(GEN x) { return (typ(x) == t_INT)? absi(x): absfrac(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) - bit_accuracy(prec)); gel(y,2) = b; return y; } return cxtofp(z, prec); } case t_QUAD: return quadtofp(z, prec); default: pari_err(typeer,"gtofp"); 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 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,lg(y)), y); avma = av; break; default: pari_err(operf,"",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(lg(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); } /* Fast implementation of 2 + nbits2nlong(x) */ INLINE long nbits2prec(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 long prec2ndec(long x) { return (long)bit_accuracy_mul(x, LOG10_2); } 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); } 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_inv(GEN a, GEN m) { GEN res; if (! invmod(a,m,&res)) pari_err(invmoder, gmodulo(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); } /*******************************************************************/ /* */ /* 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); GEN y; if (s == 0) return real_0_bit(expo(x) >> 1); if (s >= 0) return sqrtr_abs(x); y = cgetg(3,t_COMPLEX); gel(y,2) = sqrtr_abs(x); gel(y,1) = gen_0; return y; } /* 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 long degpol(GEN x) { return lg(x)-3; } INLINE long lgpol(GEN x) { return lg(x)-2; } 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_div(GEN x, GEN y) { return RgX_divrem(x,y,NULL); } INLINE GEN RgX_rem(GEN x, GEN y) { return RgX_divrem(x,y,ONLY_REM); } INLINE GEN RgXQX_div(GEN x, GEN y, GEN T) { return RgXQX_divrem(x,y,T,NULL); } INLINE GEN RgXQX_rem(GEN x, GEN y, GEN T) { return RgXQX_divrem(x,y,T,ONLY_REM); } INLINE GEN FpX_div(GEN x, GEN y, GEN p) { return FpX_divrem(x,y,p, NULL); } INLINE GEN Flx_div(GEN x, GEN y, ulong p) { return Flx_divrem(x,y,p, NULL); } INLINE GEN F2x_div(GEN x, GEN y) { return F2x_divrem(x,y, NULL); } INLINE GEN FpV_FpC_mul(GEN x, GEN y, GEN p) { return FpV_dotproduct(x,y,p); } INLINE GEN pol0_Flx(long sv) { return mkvecsmall(sv); } INLINE GEN pol1_Flx(long sv) { return mkvecsmall2(sv, 1); } INLINE GEN polx_Flx(long sv) { return mkvecsmall3(sv, 0, 1); } INLINE GEN zero_zx(long sv) { return zero_Flx(sv); } INLINE GEN polx_zx(long sv) { return polx_Flx(sv); } INLINE GEN zx_shift(GEN x, long n) { return Flx_shift(x,n); } INLINE GEN zx_renormalize(GEN x, long l) { return Flx_renormalize(x,l); } INLINE GEN zero_F2x(long sv) { return zero_Flx(sv); } INLINE GEN pol0_F2x(long sv) { return pol0_Flx(sv); } INLINE GEN pol1_F2x(long sv) { return pol1_Flx(sv); } INLINE GEN polx_F2x(long sv) { return mkvecsmall2(sv, 2); } INLINE int F2x_equal1(GEN x) { return Flx_equal1(x); } INLINE GEN Flv_copy(GEN x) { return leafcopy(x); } INLINE GEN Flx_copy(GEN x) { return leafcopy(x); } INLINE GEN vecsmall_copy(GEN x) { return leafcopy(x); } INLINE int Flx_equal1(GEN x) { return degpol(x)==0 && x[2] == 1; } INLINE GEN FpX_renormalize(GEN x, long lx) { return ZX_renormalize(x,lx); } INLINE GEN FpXX_renormalize(GEN x, long lx) { return ZX_renormalize(x,lx); } INLINE GEN FpXQX_renormalize(GEN x, long lx) { return ZX_renormalize(x,lx); } INLINE GEN F2x_renormalize(GEN x, long lx) { return Flx_renormalize(x,lx); } INLINE GEN ZX_ZXY_resultant(GEN a, GEN b) { return ZX_ZXY_rnfequation(a,b,NULL); } INLINE long sturm(GEN x) { return sturmpart(x, NULL, NULL); } INLINE GEN resultant(GEN x, GEN y) { return resultant_all(x,y,NULL); } INLINE long gval(GEN x, long v) { pari_sp av = avma; long n = ggval(x, pol_x(v)); avma = av; return n; } INLINE void RgX_shift_inplace_init(long v) { if (v) (void)cgetg(v, t_VECSMALL); } /* shift polynomial in place. assume v free cells have been left before x */ INLINE GEN RgX_shift_inplace(GEN x, long v) { long i, lx; GEN y, z; if (!v) return x; lx = lg(x); if (lx == 2) return x; y = x + v; z = x + lx; /* stackdummy from normalizepol: move it up */ if (lg(z) != v) x[lx + v] = z[0]; for (i = lx-1; i >= 2; i--) y[i] = 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_hnfremdiv(x,y,NULL); } INLINE GEN ZM_lll(GEN x, double D, long f) { return ZM_lll_norms(x,D,f,NULL); } 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_rem(GEN x, GEN y, GEN T, GEN p) { return FpXQX_divrem(x, y, T, p, ONLY_REM); } 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_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_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 GEN ell_get_roots(GEN e) { return gel(e,14); } INLINE int ell_is_inf(GEN z) { return lg(z) < 3; } INLINE int ell_is_padic(GEN x) { return lg(x) == 20 && typ(gel(x,19)) == t_INT; } INLINE int ell_is_real(GEN x) { return lg(x) == 20 && typ(gel(x,19)) != t_INT; } 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 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 gmael3(bnf,8,1,1); } INLINE GEN bnf_get_cyc(GEN bnf) { return gmael3(bnf,8,1,2); } INLINE GEN bnf_get_gen(GEN bnf) { return gmael3(bnf,8,1,3); } 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(talker,"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 gmael(bnr,5,1); } INLINE GEN bnr_get_cyc(GEN bnr) { return gmael(bnr,5,2); } INLINE GEN bnr_get_gen_nocheck(GEN bnr) { return gmael(bnr,5,3); } INLINE GEN bnr_get_gen(GEN bnr) { GEN G = bnr_get_clgp(bnr); if (lg(G) != 4) pari_err(talker,"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_cyc(GEN bid) { return gmael(bid,2,2); } INLINE GEN bid_get_gen_nocheck(GEN bid) { return gmael(bid,2,3); } INLINE GEN bid_get_gen(GEN bid) { GEN G = gel(bid, 2); if (lg(G) != 4) pari_err(talker,"missing bid generators. Use idealstar(,,2)"); return gel(G,3); } 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(gel(rnf,1)); } /* 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); } pari-2.5.5/src/headers/paritune.h0000644000175000017500000000623112147140046015307 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_INVMONTGOMERY_LIMIT; extern long Flx_REM_MONTGOMERY_LIMIT; extern long Flx_POW_MONTGOMERY_LIMIT; extern long Flx_HALFGCD_LIMIT; extern long Flx_GCD_LIMIT; extern long Flx_EXTGCD_LIMIT; extern long FpX_INVMONTGOMERY_LIMIT; extern long FpX_REM_MONTGOMERY_LIMIT; extern long FpX_POW_MONTGOMERY_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_INVMONTGOMERY_LIMIT __Flx_INVMONTGOMERY_LIMIT # define Flx_REM_MONTGOMERY_LIMIT __Flx_REM_MONTGOMERY_LIMIT # define Flx_POW_MONTGOMERY_LIMIT __Flx_POW_MONTGOMERY_LIMIT # define Flx_HALFGCD_LIMIT __Flx_HALFGCD_LIMIT # define Flx_GCD_LIMIT __Flx_GCD_LIMIT # define Flx_EXTGCD_LIMIT __Flx_EXTGCD_LIMIT # define FpX_INVMONTGOMERY_LIMIT __FpX_INVMONTGOMERY_LIMIT # define FpX_REM_MONTGOMERY_LIMIT __FpX_REM_MONTGOMERY_LIMIT # define FpX_POW_MONTGOMERY_LIMIT __FpX_POW_MONTGOMERY_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.5.5/src/headers/paristio.h0000644000175000017500000001020112147140046015302 0ustar billbill/* $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. */ /* This file contains memory and I/O management definitions */ typedef struct { long s, us; } pari_timer; typedef unsigned char *byteptr; typedef ulong pari_sp; /* 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; struct pari_compilestate comp; }; struct gp_context { long listloc; long err_catch; struct pari_evalstate eval; struct pari_parsestate parse; pariFILE *file; void *err_data; }; 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 */ } hashtable; typedef struct { long offset; 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 const char *errmessage[]; 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.5.5/src/headers/parierr.h0000644000175000017500000000212612147140046015123 0ustar billbill/* $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. */ enum { /* Force errors into non-0 */ syntaxer = 1, bugparier, /* untrappable errors */ alarmer, openfiler, talker, flagerr, impl, archer, notfuncer, precer, typeer, consister, user, errpile, overflower, /* alglin.c */ matinv1, mattype1, /* arith.c */ arither1, primer1, invmoder, /* base.c */ constpoler, notpoler, redpoler, zeropoler, /* gen.c */ operi, operf, gdiver, /* init.c */ memer, /* trans.c */ negexper, sqrter5, /* NO ERROR */ noer }; enum { warner, warnprec, warnfile, warnmem }; pari-2.5.5/src/headers/paridecl.h0000644000175000017500000034272112147140046015252 0ustar billbill/* $Id$ 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" /* 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_ZC(GEN x); GEN F2m_to_ZM(GEN z); void F2v_add_inplace(GEN x, GEN y); GEN F2x_1_add(GEN y); GEN F2x_add(GEN x, GEN y); long F2x_degree(GEN x); GEN F2x_deriv(GEN x); GEN F2x_divrem(GEN x, GEN y, GEN *pr); GEN F2x_extgcd(GEN a, GEN b, GEN *ptu, GEN *ptv); GEN F2x_gcd(GEN a, GEN b); GEN F2x_mul(GEN x, GEN y); GEN F2x_rem(GEN x, GEN y); GEN F2x_sqr(GEN x); GEN F2x_to_F2v(GEN x, long n); GEN F2x_to_Flx(GEN x); GEN F2x_to_ZX(GEN x); GEN F2xC_to_ZXC(GEN x); GEN F2xV_to_F2m(GEN v, long n); 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_powers(GEN x, long l, GEN T); GEN F2xq_sqr(GEN x,GEN pol); GEN F2xq_sqrt(GEN a, 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 Z_to_F2x(GEN x, long sv); GEN ZM_to_F2m(GEN x); GEN ZV_to_F2v(GEN x); GEN ZX_to_F2x(GEN x); GEN ZXX_to_F2xX(GEN B, long v); GEN gener_F2xq(GEN T, GEN *po); GEN random_F2x(long d, long vs); /* 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_add(GEN x, GEN y, ulong p); GEN Flx_deflate(GEN x0, long d); GEN Flx_deriv(GEN z, 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); 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_halfgcd(GEN a, GEN b, ulong p); GEN Flx_inflate(GEN x0, long d); GEN Flx_invMontgomery(GEN T, ulong p); int Flx_is_squarefree(GEN z, 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_Montgomery(GEN x, GEN mg, GEN T, 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_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_ZX(GEN z); GEN Flx_to_ZX_inplace(GEN z); long Flx_val(GEN x); long Flx_valrem(GEN x, GEN *Z); GEN FlxC_to_ZXC(GEN x); GEN FlxM_to_ZXM(GEN z); GEN FlxV_Flc_mul(GEN V, GEN W, ulong p); GEN FlxV_to_Flm(GEN v, long n); GEN FlxX_add(GEN P, GEN Q, ulong p); 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_ZXX(GEN B); GEN FlxY_Flx_div(GEN x, GEN y, ulong p); GEN FlxYqQ_pow(GEN x, GEN n, GEN S, 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); GEN Flxq_log(GEN a, GEN g, GEN ord, GEN T, ulong 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_powers(GEN x, long l, GEN T, ulong p); GEN Flxq_sqr(GEN y,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_roots_to_pol(GEN V, GEN T, ulong p, long v); 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_mul(GEN x, GEN y, GEN T, ulong p); GEN FlxqX_normalize(GEN z, GEN T, ulong p); GEN FlxqX_red(GEN z, GEN T, ulong p); GEN FlxqX_safegcd(GEN P, GEN Q, GEN T, ulong p); GEN FlxqX_sqr(GEN x, 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_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_sqr(GEN x, GEN S, GEN T, ulong p); GEN FlxqXV_prod(GEN V, 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); GEN pol1_FlxX(long v, long sv); GEN random_Flx(long d1, long v, ulong p); /* FpE.c */ GEN FpE_add(GEN P, GEN Q, GEN a4, GEN p); GEN FpE_dbl(GEN P, GEN a4, GEN p); GEN FpE_neg(GEN P, GEN p); GEN FpE_order(GEN z, GEN o, GEN a4, GEN p); GEN FpE_mul(GEN P, GEN n, GEN a4, GEN p); GEN FpE_sub(GEN P, GEN Q, GEN a4, 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 random_FpE(GEN a4, GEN a6, GEN p); /* FpX.c */ 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_sub(GEN x, GEN y, GEN p); GEN FpX_Fp_sub_shallow(GEN y,GEN x,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_divrem(GEN x, GEN y, GEN p, GEN *pr); GEN FpX_div_by_X_x(GEN a, GEN x, GEN p, GEN *r); 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_halfgcd(GEN x, GEN y, GEN p); GEN FpX_invMontgomery(GEN T, GEN p); int FpX_is_squarefree(GEN f, GEN p); GEN FpX_mul(GEN x, GEN 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_rem_Montgomery(GEN x, GEN mg, GEN T, 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_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_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_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 FpXV_prod(GEN V, GEN p); GEN FpXV_red(GEN z, GEN p); GEN FqV_inv(GEN x, GEN T, GEN p); GEN gener_FpXQ(GEN T, GEN p, GEN *o); GEN random_FpX(long d, long v, GEN p); /* FpV.c */ 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); 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_mul(GEN x, GEN y, ulong p); 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_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_red(GEN z, GEN p); GEN FpM_to_mod(GEN z, GEN p); GEN FpC_add(GEN x, GEN y, GEN p); GEN FpC_sub(GEN x, GEN y, 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 FpX_to_mod(GEN z, GEN p); /* 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_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_isdiagonal(GEN x); int RgM_isidentity(GEN x); int RgM_isscalar(GEN x, GEN s); GEN RgM_mul(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_zc_mul(GEN x, GEN y); GEN RgM_zm_mul(GEN x, GEN y); 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); 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); int isdiagonal(GEN x); GEN matid(long n); GEN matid_Flm(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 QX_ZXQV_eval(GEN P, GEN V, GEN dV); GEN QXQ_powers(GEN a, long n, GEN T); GEN QXQV_to_mod(GEN V, GEN T); GEN QXQXV_to_mod(GEN V, GEN T); 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 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 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_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); long RgX_equal_var(GEN x, GEN y); 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_mul(GEN x,GEN y); GEN RgX_mulXn(GEN x, long d); 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(GEN x); GEN RgX_rescale(GEN P, GEN h); GEN RgX_shift(GEN a, long n); GEN RgX_shift_shallow(GEN x, long n); GEN RgX_sqr(GEN x); 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); /* ZV.c */ 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 ZM_reducemodlll(GEN x,GEN y); GEN ZM_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_hnfremdiv(GEN x, GEN y, GEN *Q); long ZM_max_lg(GEN x); GEN ZM_mul(GEN x, GEN y); GEN ZM_neg(GEN x); GEN ZM_pow(GEN x, GEN n); 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_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); int ZV_equal0(GEN V); GEN ZV_content(GEN x); GEN ZV_dotproduct(GEN x,GEN y); GEN ZV_dotsquare(GEN x); int ZV_equal(GEN V, GEN W); 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 zm_to_ZM(GEN z); int zv_cmp0(GEN V); long zv_content(GEN x); int zv_equal(GEN V, GEN W); GEN zv_neg(GEN x); long zv_prod(GEN v); long zv_sum(GEN v); int ZM_ishnf(GEN x); int ZM_isidentity(GEN x); void RgM_check_ZM(GEN A, const char *s); void RgV_check_ZV(GEN A, const char *s); /* ZX.c */ void RgX_check_ZX(GEN x, const char *s); void RgX_check_ZXY(GEN x, const char *s); GEN ZXV_Z_mul(GEN y, GEN x); long ZXY_max_lg(GEN x); GEN ZX_Z_add(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); long ZX_max_lg(GEN x); GEN ZX_mul(GEN x, GEN y); GEN ZX_mulspec(GEN a, GEN b, long na, long nb); GEN ZX_neg(GEN x); GEN ZX_rem(GEN x, GEN y); GEN ZX_renormalize(GEN x, long lx); GEN ZX_rescale(GEN P, GEN h); 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 Z_ZX_sub(GEN x, GEN y); 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_deplin(GEN x); ulong F2m_det(GEN x); ulong F2m_det_sp(GEN x); GEN F2m_ker(GEN x); GEN F2m_ker_sp(GEN x, long deplin); 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_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 FlxqM_ker(GEN x, GEN T, ulong 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_gauss(GEN a, GEN b, GEN T, GEN p); GEN FqM_ker(GEN x, GEN T, GEN p); GEN FqM_suppl(GEN x, GEN T, GEN p); GEN QM_inv(GEN M, GEN dM); GEN RgM_diagonal(GEN m); GEN RgM_diagonal_shallow(GEN m); GEN RgM_inv_upper(GEN a); GEN RgM_solve(GEN a, GEN b); GEN RgM_solve_realimag(GEN x, GEN y); GEN ZM_detmult(GEN A); GEN ZM_inv(GEN M, GEN dM); GEN apply0(GEN f, GEN A); 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 diagonal(GEN x); GEN diagonal_shallow(GEN x); GEN eigen(GEN x, long prec); GEN extract0(GEN x, GEN l1, GEN l2); GEN gauss(GEN a, GEN b); GEN gaussmodulo(GEN M, GEN D, GEN Y); GEN gaussmodulo2(GEN M, GEN D, GEN Y); GEN genapply(void *E, GEN (*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 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 matimage0(GEN x,long flag); GEN matker0(GEN x, long flag); GEN matmuldiagonal(GEN x, GEN d); GEN matmultodiagonal(GEN x, GEN y); 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 select0(GEN A, GEN f); GEN shallowextract(GEN x, GEN L); GEN shallowtrans(GEN x); GEN split_realimag(GEN x, long r1, long r2); GEN suppl(GEN x); /* alglin2.c */ 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 charpoly0(GEN x, long v,long flag); GEN gnorm(GEN x); GEN gnorml1(GEN x,long prec); GEN gnorml2(GEN x); GEN gsupnorm(GEN x, long prec); void gsupnorm_aux(GEN x, GEN *m, GEN *msq); 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); /* 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, char *name, 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 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_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); long Z_isanypower(GEN x, GEN *y); long Z_isfundamental(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 bestappr0(GEN x, GEN a, GEN b); GEN bestappr(GEN x, GEN k); long cgcd(long a,long b); ulong ugcd(ulong a,ulong b); GEN chinese1(GEN x); GEN chinese1_coprime_Z(GEN x); GEN chinese(GEN x, GEN y); GEN classno2(GEN x); GEN classno(GEN x); long clcm(long a,long b); GEN contfrac0(GEN x, GEN b, long flag); GEN fibo(long n); GEN gboundcf(GEN x, long k); GEN gcf2(GEN b, GEN x); GEN gcf(GEN x); ulong pgener_Fl_local(ulong p, GEN L); ulong pgener_Fl(ulong p); GEN pgener_Fp_local(GEN p, GEN L); GEN pgener_Fp(GEN p); ulong pgener_Zl(ulong p); GEN pgener_Zp(GEN p); long gisanypower(GEN x, GEN *pty); GEN gisfundamental(GEN x); GEN gissquareall(GEN x, GEN *pt); GEN gissquare(GEN x); GEN gkronecker(GEN x, GEN y); GEN hclassno(GEN x); long hilbert(GEN x, GEN y, GEN p); long hilbertii(GEN x, GEN y, GEN p); long ispower(GEN x, GEN k, GEN *pty); long krois(GEN x, long 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); GEN mpfact(long n); 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); GEN sqrtint(GEN a); GEN mulu_interval(ulong a, ulong b); long uissquareall(ulong A, ulong *sqrtA); GEN znorder(GEN x, GEN o); GEN znlog(GEN x, GEN g, GEN o); GEN znprimroot(GEN m); GEN znprimroot0(GEN m); GEN znstar(GEN x); /* arith2.c */ long Z_issquarefree(GEN x); GEN Z_factor_limit(GEN n, ulong all); GEN Z_factor_until(GEN n, GEN limit); GEN Z_smoothen(GEN N, GEN L, GEN *pP, GEN *pe); long bigomega(GEN n); GEN boundfact(GEN n, ulong lim); GEN core(GEN n); 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 divisors(GEN n); GEN divisorsu(ulong n); GEN factor_pn_1(GEN p, long n); GEN factorint(GEN n, long flag); GEN factoru(ulong n); GEN factoru_pow(ulong n); GEN gbigomega(GEN n); GEN gissquarefree(GEN x); GEN gmoebius(GEN n); GEN gnumbdiv(GEN n); GEN gomega(GEN n); GEN geulerphi(GEN n); GEN gsumdiv(GEN n); GEN gsumdivk(GEN n,long k); byteptr initprimes(ulong maxnum); ulong init_primepointer(ulong a, ulong p, byteptr *ptr); long issquarefree(GEN x); ulong maxprime(void); void maxprime_check(ulong c); long moebius(GEN n); GEN numbdiv(GEN n); long omega(GEN n); GEN eulerphi(GEN n); GEN sumdiv(GEN n); GEN sumdivk(GEN n,long k); ulong eulerphiu(ulong n); GEN Z_factor(GEN 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 Polred(GEN x, long flag, GEN fa); GEN T2_from_embed(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 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 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 ordred(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 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); long ZpX_disc_val(GEN f, GEN p); GEN ZpX_gcd(GEN f1,GEN f2,GEN pm); GEN ZpX_reduced_resultant(GEN x, GEN y, GEN pm); GEN ZpX_reduced_resultant_fast(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 rnf_fix_pol(GEN nf, GEN x, int lift); 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,long flag,GEN p); GEN nfbasis0(GEN x,long flag,GEN p); GEN nfdisc0(GEN x,long flag, GEN p); void nfmaxord(nfmaxord_t *S, GEN f, long flag, GEN w); 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 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 rnfpolredabs(GEN nf, GEN pol, long flag); 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 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 rnfalgtobasis(GEN rnf, GEN x); GEN rnfbasistoalg(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 zk_multable(GEN nf, GEN x); GEN ei_multable(GEN nf, long i); GEN zk_scalar_or_multable(GEN, GEN x); /* base4.c */ GEN RM_round_maxrank(GEN G); GEN famat_inv(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 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 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 rnfelementabstorel(GEN rnf, GEN x); GEN rnfelementdown(GEN rnf, GEN x); GEN rnfelementreltoabs(GEN rnf, GEN x); GEN rnfelementup(GEN rnf, GEN x); GEN rnfidealabstorel(GEN rnf, GEN x); GEN rnfidealdown(GEN rnf, GEN x); GEN rnfidealhermite(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 easy(void *E, GEN, GEN, GEN)); GEN gen_Shanks_sqrtn(GEN a, GEN n, GEN q, GEN *zetan, void *E, const struct bb_group *grp); GEN gen_eltorder(GEN x, 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 easy(void*E, GEN, GEN, GEN)); GEN gen_pow(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)); GEN gen_powu(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)); /* bibli1.c */ GEN Q_from_QR(GEN x, long prec); GEN R_from_QR(GEN x, long prec); GEN algdep(GEN x, long n); GEN algdep0(GEN x, long n, long bit); GEN gram_matrix(GEN M); GEN lindep(GEN x); GEN lindep0(GEN x, long flag); GEN lindep2(GEN x, long bit); GEN minim(GEN a, GEN borne, GEN stockmax); GEN qfrep0(GEN a, GEN borne, long flag); GEN qfminim0(GEN a, GEN borne, GEN stockmax,long flag, long prec); GEN minim2(GEN a, GEN borne, GEN stockmax); GEN perf(GEN a); char* stackmalloc(size_t N); GEN zncoppersmith(GEN P0, GEN N, GEN X, GEN B) ; /* bibli2.c */ GEN QXQ_reverse(GEN a, GEN T); 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); 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 modreverse(GEN x); GEN RgXQ_reverse(GEN a, GEN T); 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 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); GEN vecsort(GEN x, GEN k); GEN vecsort0(GEN x, GEN k, long flag); 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); /* 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); 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 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, long bound); GEN discrayabslistlong(GEN bnf, long 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 flag); 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 shallowconcat(GEN x, GEN y); GEN shallowconcat1(GEN x); 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_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_strictmatch(const char *v, long flag); GEN sd_toggle(const char *v, long flag, const char *s, int *ptn); GEN sd_string(const char *v, long flag, const char *s, char **f); 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 ellgenerators(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 */ GEN addell(GEN e, GEN z1, GEN z2); GEN akell(GEN e, GEN n); GEN anell(GEN e, long n); GEN bilhell(GEN e, GEN z1, GEN z2, long prec); void checkell(GEN e); void checkell_real(GEN e); void checkell_padic(GEN e); void checksmallell(GEN e); void checkellpt(GEN z); void checkell5(GEN e); GEN ell_to_small_red(GEN e, GEN *N); GEN ellap(GEN e, GEN p); GEN ellchangecurve(GEN e, 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 ellglobalred(GEN e1); GEN ellgroup(GEN E, GEN p); GEN ellheight0(GEN e, GEN a, long flag,long prec); GEN ellinit(GEN x, long prec); GEN ellinit0(GEN x,long flag,long prec); GEN ellinit_padic(GEN x, GEN p, long prec); GEN ellinit_real(GEN x, 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 ellorder(GEN e, GEN p, GEN o); GEN ellordinate(GEN e, GEN x, long prec); GEN ellrandom(GEN e); long ellrootno(GEN e, GEN p); long ellrootno_global(GEN e, GEN N); GEN ellsigma(GEN om, GEN z, long flag, long prec); GEN elltaniyama(GEN e, long prec); GEN elltatepairing(GEN E, GEN t, GEN s, GEN m); GEN elltors0(GEN e, long flag); GEN ellweilpairing(GEN E, GEN t, GEN s, GEN m); GEN ellwp0(GEN e, GEN z, long flag, long prec, long PREC); GEN ellzeta(GEN om, GEN z, 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 ellchangepoint(GEN x, GEN ch); GEN ellchangepointinv(GEN x, GEN ch); GEN pointell(GEN e, GEN z, long prec); GEN powell(GEN e, GEN z, GEN n); GEN smallellinit(GEN x); GEN subell(GEN e, GEN z1, GEN z2); GEN elltors(GEN e); GEN weipell(GEN e, long precdl); GEN zell(GEN e, GEN z, long prec); /* ellsea.c */ 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); 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_read_file(char *s); GEN gp_read_stream(FILE *f); GEN gp_readvec_file(char *s); GEN gp_readvec_stream(FILE *f); 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); GEN pari_add_hist(GEN z); 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, ...); GEN pari_get_hist(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, 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); 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 printtex(GEN g); 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 */ 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); void closure_disassemble(GEN n); void closure_err(void); 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 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_evalvoid(void *E, GEN x); long loop_break(void); GEN next0(long n); 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); int FF_equal0(GEN x); int FF_equal1(GEN x); int FF_equalm1(GEN x); GEN FF_conjvec(GEN x); GEN FF_div(GEN a, GEN b); int FF_equal(GEN a, GEN b); 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); 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_FpXQ(GEN x); GEN FF_to_FpXQ_i(GEN x); GEN FF_trace(GEN x); GEN FF_zero(GEN a); 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 is_Z_factor(GEN f); /* galconj.c */ GEN checkgal(GEN gal); GEN checkgroup(GEN g, GEN *S); 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); /* 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); /* galpol.c */ GEN galoisnbpol(long a); GEN galoisgetpol(long a, long b, long s); /* gen2.c */ GEN gassoc_proto(GEN f(GEN,GEN),GEN,GEN); GEN map_proto_G(GEN f(GEN), GEN x); GEN map_proto_GG(GEN f(GEN,GEN), GEN x, GEN n); GEN map_proto_GL(GEN f(GEN,long), GEN x, long y); GEN map_proto_lG(long f(GEN), GEN x); GEN map_proto_lGG(long f(GEN,GEN), GEN x, GEN n); GEN map_proto_lGL(long f(GEN,long), GEN x, long y); long Q_pval(GEN x, GEN p); long RgX_val(GEN x); long RgX_valrem(GEN x, GEN *z); long RgX_valrem_inexact(GEN x, GEN *Z); 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_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 gcmpX(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 ggval(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); long sizedigit(GEN x); long u_lval(ulong x, ulong p); long u_lvalrem(ulong x, ulong p, ulong *py); long u_pval(ulong x, GEN p); long u_pvalrem(ulong x, GEN p, ulong *py); GEN vecmax(GEN x); 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 RgM_mulreal(GEN x, GEN y); GEN RgX_RgM_eval(GEN x, GEN y); GEN RgX_RgM_eval_col(GEN x, GEN M, long c); GEN RgX_RgMV_eval(GEN x, GEN y); GEN RgX_deflate_max(GEN x0, long *m); 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 gand(GEN x, GEN y); 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 gor(GEN x, GEN y); 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 gtopoly(GEN x, long v); GEN gtopolyrev(GEN x, long v); GEN gtoser(GEN x, long v, long precdl); GEN gtovec(GEN x); GEN gtovecrev(GEN x); GEN gtovecsmall(GEN x); 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); 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 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); GEN polcoeff0(GEN x,long n,long v); GEN polcoeff_i(GEN x, long n, long v); long poldegree(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 qfeval(GEN q, GEN x); GEN qfevalb(GEN q, GEN x, GEN y); GEN real_i(GEN x); GEN recip(GEN x); GEN round0(GEN x, GEN *pte); GEN roundr(GEN x); GEN roundr_safe(GEN x); GEN scalarpol(GEN x, long v); GEN scalarser(GEN x, long v, long prec); 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); /* 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*)); 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 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 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 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 gnextprime(GEN n); GEN gprecprime(GEN n); int is_357_power(GEN x, GEN *pt, ulong *mask); int is_pth_power(GEN x, GEN *pt, ulong *curexp, ulong cutoffbits); GEN nextprime(GEN n); GEN precprime(GEN n); ulong unextprime(ulong n); /* 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_block(void); void dbg_gerepile(pari_sp av); void dbg_gerepileupto(GEN q); void dbg_release(void); long err_catch(long errnum, jmp_buf *penv); void err_leave(long n); GEN gclone(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, ...); GEN newblock(size_t n); 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, ...); 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 *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_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_w(GEN x); GEN member_zk(GEN x); GEN member_zkst(GEN bid); /* mp.c */ ulong Fl_inv(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 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 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); int ratlift(GEN x, GEN m, GEN amax, GEN bmax, GEN *a, GEN *b); 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 trunc2nr_lg(GEN x, long lx, long n); GEN truncr(GEN x); ulong umodiu(GEN y, ulong x); long vals(ulong x); /* nffactor.c */ 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; /* part.c */ GEN numbpart(GEN x); GEN partitions(long n, long amax); /* 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); 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); GEN vecvecsmall_sort(GEN x); long vecvecsmall_search(GEN x, GEN y, long flag); /* polarit1.c */ 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); 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 p, GEN T); 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 p, GEN T); 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 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 polrootsff(GEN f, GEN p, GEN T); GEN rootmod0(GEN f, GEN p,long flag); GEN rootpadic(GEN f, GEN p, long r); GEN rootpadicfast(GEN f, GEN p, long e); /* 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_liftroot(GEN f, GEN a, GEN p, long e); GEN ZpX_liftroots(GEN f, GEN S, GEN q, long e); GEN ZpXQX_liftroot(GEN f, GEN a, GEN T, GEN p, long e); GEN ZpXQ_sqrtnlift(GEN b, GEN n, GEN a, GEN T, GEN p, long e); GEN ZpX_liftfact(GEN pol, GEN Q, GEN T, GEN p, long e, GEN pe); 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); /* 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 gisirreducible(GEN x); 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); GEN leftright_pow_fold(GEN x, GEN n, void *data, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)); GEN leftright_pow_u_fold(GEN x, ulong n, void *data, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)); 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 vecbezout(GEN x, GEN y); GEN vecbezoutres(GEN x, GEN y); /* polarit3.c */ GEN FlxX_resultant(GEN u, GEN v, ulong p, long sx); GEN Flx_FlxY_resultant(GEN a, GEN b, ulong pp); GEN Flx_roots_naive(GEN f, ulong p); GEN FpV_polint(GEN xa, GEN ya, GEN p, long v); 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_FpXY_resultant(GEN a, GEN b0, GEN p); GEN FpX_factorff_irred(GEN P, GEN Q, GEN l); 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 FpXQ_ffisom_inv(GEN S,GEN Tp, GEN p); GEN FpXQX_gcd(GEN P, GEN Q, 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_sqr(GEN x, GEN T, GEN p); GEN FpXQX_extgcd(GEN x, GEN y, GEN T, GEN p, GEN *ptu, GEN *ptv); GEN FpXQX_divrem(GEN x, GEN y, GEN T, GEN p, GEN *pr); GEN FpXQX_FpXQ_mul(GEN P, GEN U, 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_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_sqr(GEN x, GEN S, GEN T, GEN p); GEN FpXQXV_prod(GEN V, GEN Tp, GEN p); GEN FpXV_FpC_mul(GEN V, GEN W, GEN p); GEN FpXX_Fp_mul(GEN x, GEN y, GEN p); GEN FpXX_add(GEN x, GEN y, GEN p); GEN FpXX_red(GEN z, GEN p); GEN FpXX_sub(GEN x, GEN y, 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 Fq_inv(GEN x, GEN T, GEN p); GEN Fq_invsafe(GEN x, GEN T, GEN p); GEN Fq_add(GEN x, GEN y, GEN T/*unused*/, GEN p); GEN Fq_Fp_mul(GEN x, GEN y, GEN T, GEN p); GEN Fq_mul(GEN x, GEN y, 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_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 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_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 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); ulong Rg_to_Fl(GEN x, ulong p); GEN Rg_to_Fp(GEN x, GEN p); GEN Rg_to_FpXQ(GEN x, GEN T, GEN p); GEN RgC_to_FpC(GEN x, GEN p); int RgM_is_FpM(GEN x, GEN *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, GEN qp, ulong p); GEN Z_init_CRT(ulong Hp, ulong p); int ZM_incremental_CRT(GEN *H, GEN Hp, GEN q, GEN qp, ulong p); GEN ZM_init_CRT(GEN Hp, ulong p); int ZX_incremental_CRT(GEN *ptH, GEN Hp, GEN q, GEN qp, ulong p); GEN ZX_init_CRT(GEN Hp, ulong p, long v); long brent_kung_optpow(long d, long n); GEN ffinit(GEN p, long n, long v); GEN Kronecker_to_mod(GEN z, GEN pol); GEN init_Fq(GEN p, long n, long v); GEN pol_x_powers(long N, long v); GEN mod_to_Kronecker(GEN P, GEN Q); /* 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); long isprime(GEN x); long ispseudoprime(GEN x, long flag); long millerrabin(GEN n, long k); GEN prime(long n); GEN primepi(GEN x); GEN primes(long n); GEN primes_zv(long m); GEN removeprimes(GEN primes); int uisprime(ulong n); ulong uprime(long n); ulong uprimepi(ulong n); /* 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 cleanroots(GEN x,long l); int isrealappr(GEN x, long l); GEN roots(GEN x,long l); GEN roots0(GEN x,long flag,long l); /* polsubcyclo.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); GEN forvec_start(GEN x, long flag, GEN *d, GEN (**next)(GEN,GEN)); 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); 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_issquare(GEN x, GEN n); GEN Zn_sqrt(GEN x, GEN n); GEN agm(GEN x, GEN y, long prec); GEN consteuler(long prec); GEN constlog2(long prec); GEN constpi(long prec); GEN exp_Ir(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 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 mpexp(GEN x); GEN mpexp1(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 teich(GEN x); ulong upowuu(ulong p, ulong k); /* trans2.c */ GEN Qp_gamma(GEN x); GEN bernfrac(long n); GEN bernreal(long n, long prec); GEN gach(GEN x, long prec); GEN gacos(GEN x, long prec); GEN garg(GEN x, long prec); GEN gash(GEN x, long prec); GEN gasin(GEN x, long prec); GEN gatan(GEN x, long prec); GEN gath(GEN x, long prec); GEN gch(GEN x, long prec); GEN ggamd(GEN x, long prec); GEN ggamma(GEN x, long prec); GEN glngamma(GEN x, long prec); GEN gpsi(GEN x, long prec); GEN gsh(GEN x, long prec); GEN gth(GEN x, long prec); void mpbern(long nomb, long prec); GEN mpfactr(long n, long prec); /* 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 mpveceint1(GEN C, GEN eC, long n); GEN mpvecpow(GEN e, long 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 veceint1(GEN nmax, GEN C, long prec); GEN vecthetanullk(GEN q, 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); /* 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_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 GEN absi(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_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 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 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 icopy_avma(GEN x, pari_sp av); 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 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 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_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 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 long smodis(GEN x, long y); INLINE long smodss(long x, long y); INLINE void stackdummy(pari_sp av, pari_sp ltop); 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 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_ideal(GEN bid); INLINE GEN bid_get_mod(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 GEN ell_get_roots(GEN e); INLINE int ell_is_inf(GEN z); INLINE int ell_is_padic(GEN e); INLINE int ell_is_real(GEN e); INLINE GEN ellinf(void); 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_degree(GEN rnf); 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 FpXQX_rem(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_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 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 GEN F2x_div(GEN x, GEN y); INLINE GEN F2x_renormalize(GEN x, long lx); INLINE GEN F2m_copy(GEN x); 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 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_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_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 int QV_isscalar(GEN x); INLINE GEN RgC_fpnorml2(GEN x, long prec); INLINE GEN RgC_gtofp(GEN x, long prec); INLINE GEN RgM_fpnorml2(GEN x, long prec); INLINE GEN RgM_gtofp(GEN x, long prec); INLINE GEN RgM_inv(GEN a); INLINE int RgM_is_ZM(GEN x); INLINE GEN RgM_minor(GEN a, long i, long j); INLINE GEN RgM_shallowcopy(GEN x); INLINE int RgV_isscalar(GEN x); INLINE int RgX_is_monomial(GEN x); INLINE int RgX_is_rational(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_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 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 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 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 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 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 lgpol(GEN x); INLINE GEN matpascal(long n); INLINE GEN mkcol(GEN x); INLINE GEN mkcol2(GEN x, GEN y); INLINE GEN mkcolcopy(GEN x); INLINE GEN mkcomplex(GEN x, GEN y); 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 mkmatcopy(GEN x); INLINE GEN mkpolmod(GEN x, GEN y); INLINE GEN mkquad(GEN n, GEN x, GEN y); INLINE GEN mkrfrac(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 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 nbits2prec(long 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 prec2ndec(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 stack_alloc(pari_stack *s, long nb); INLINE void** stack_base(pari_stack *s); INLINE void stack_delete(pari_stack *s); INLINE void stack_init(pari_stack *s, size_t size, void **data); INLINE long stack_new(pari_stack *s); INLINE void 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_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 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 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); pari-2.5.5/src/headers/paricast.h0000644000175000017500000000252512141040641015262 0ustar billbill/* $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. */ #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.5.5/src/headers/parisys.h0000644000175000017500000000402612141040641015144 0ustar billbill/* $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. */ /* 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.5.5/src/headers/pari.h0000644000175000017500000000267512147140046014423 0ustar billbill/* $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. */ #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" #ifndef PARI_NO_MPINL_H # include "mpinl.h" #endif #ifndef PARI_NO_PARIINL_H # include "pariinl.h" #endif ENDEXTERN #endif pari-2.5.5/src/systems/0000755000175000017500000000000012212611624013377 5ustar billbillpari-2.5.5/src/systems/os2/0000755000175000017500000000000012212611624014102 5ustar billbillpari-2.5.5/src/systems/os2/dlfcn.h0000644000175000017500000000021411636712103015341 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.5.5/src/systems/os2/os2.c0000644000175000017500000001333711636712103014763 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.5.5/src/systems/os2/pari.def.base0000644000175000017500000000040111636712103016424 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.5.5/src/systems/mingw/0000755000175000017500000000000012212611624014520 5ustar billbillpari-2.5.5/src/systems/mingw/mingw.h0000644000175000017500000000135512147140047016021 0ustar billbill/* $Id$ 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 */ char* win32_datadir(void); void win32_ansi_fputs(const char* s, void* f); int win32_terminal_width(void); int win32_terminal_height(void); pari-2.5.5/src/systems/mingw/mingw.c0000644000175000017500000000566712147140047016026 0ustar billbill/* $Id$ 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 "mingw.h" 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); } 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; } 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); } 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); } pari-2.5.5/src/systems/darwin/0000755000175000017500000000000012212611624014663 5ustar billbillpari-2.5.5/src/systems/darwin/dlfcn.h0000644000175000017500000000440111636712103016124 0ustar billbill/* $Id$ */ /* 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.5.5/src/systems/darwin/darwin.c0000644000175000017500000001421211636712103016316 0ustar billbill/* $Id$ */ /* 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.5.5/src/kernel/0000755000175000017500000000000012212611624013150 5ustar billbillpari-2.5.5/src/kernel/ppc/0000755000175000017500000000000012212611624013732 5ustar billbillpari-2.5.5/src/kernel/ppc/asm0.h0000644000175000017500000000503312141040641014740 0ustar billbill/* $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. */ /* 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.5.5/src/kernel/none/0000755000175000017500000000000012212611624014107 5ustar billbillpari-2.5.5/src/kernel/none/gcdll.c0000644000175000017500000011442512147140046015351 0ustar billbill#line 2 "../src/kernel/none/gcdll.c" /* $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. */ /***********************************************************************/ /** **/ /** GCD **/ /** **/ /***********************************************************************/ /* Fast ulong gcd. Called with y odd; x can be arbitrary (but will most of * the time be smaller than y). */ /* Gotos are Harmful, and Programming is a Science. E.W.Dijkstra. */ ulong gcduodd(ulong x, ulong y) /* assume y&1==1, y > 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_inv(ulong x, ulong p) { long s; ulong xv, xv1, g = xgcduu(p, x, 1, &xv, &xv1, &s); if (g != 1UL) pari_err(invmoder, mkintmod(utoi(x), utoi(p))); xv = xv1 % p; if (s < 0) xv = p - xv; return xv; } #if 0 /* assume m > 0 */ long Fl_inv_signed(long a, long m) { if (a >= 0) { if (a > m) a %= m; } else { if (-a > m) a %= m; a += m; } return (long)Fl_inv((ulong)a, (ulong)m); } #endif pari-2.5.5/src/kernel/none/add.c0000644000175000017500000002032012147140046015002 0ustar billbill#line 2 "../src/kernel/none/add.c" /* $Id$ 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; } /* 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 = lx - ly; if (i==0) /* lx == ly */ { i = absi_cmp_lg(x,y,lx); if (!i) return gen_0; } if (i<0) { sx=sy; swapspec(x,y, lx,ly); } /* ensure |x| >= |y| */ 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 + nbits2nlong(-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 + nbits2nlong(-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] = 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] = 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.5.5/src/kernel/none/divll.h0000644000175000017500000001544112147140046015401 0ustar billbill#line 2 "../src/kernel/none/divll.h" /* $Id$ 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-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.5.5/src/kernel/none/tune-gen.h0000644000175000017500000000366312147140046016014 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_INVMONTGOMERY_LIMIT = __Flx_INVMONTGOMERY_LIMIT; long Flx_REM_MONTGOMERY_LIMIT = __Flx_REM_MONTGOMERY_LIMIT; long Flx_POW_MONTGOMERY_LIMIT = __Flx_POW_MONTGOMERY_LIMIT; long Flx_HALFGCD_LIMIT = __Flx_HALFGCD_LIMIT; long Flx_GCD_LIMIT = __Flx_GCD_LIMIT; long Flx_EXTGCD_LIMIT = __Flx_EXTGCD_LIMIT; long FpX_INVMONTGOMERY_LIMIT = __FpX_INVMONTGOMERY_LIMIT; long FpX_REM_MONTGOMERY_LIMIT = __FpX_REM_MONTGOMERY_LIMIT; long FpX_POW_MONTGOMERY_LIMIT = __FpX_POW_MONTGOMERY_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.5.5/src/kernel/none/addll.h0000644000175000017500000000620212147140046015342 0ustar billbill#line 2 "../src/kernel/none/addll.h" /* $Id$ 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-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.5.5/src/kernel/none/tune.h0000644000175000017500000000607212147140046015242 0ustar billbill#ifdef LONG_IS_64BIT #define __MULII_KARATSUBA_LIMIT 18 #define __SQRI_KARATSUBA_LIMIT 34 #define __MULII_FFT_LIMIT 1386 #define __SQRI_FFT_LIMIT 1386 #define __MULRR_MULII_LIMIT 191 #define __Fp_POW_REDC_LIMIT 99 #define __Fp_POW_BARRETT_LIMIT 97 #define __INVNEWTON_LIMIT 656 #define __DIVRR_GMP_LIMIT -1 #define __EXPNEWTON_LIMIT 66 #define __LOGAGM_LIMIT 24 #define __LOGAGMCX_LIMIT 30 #define __AGM_ATAN_LIMIT 66 #define __INVMOD_GMP_LIMIT -1 #define __Flx_MUL_KARATSUBA_LIMIT 115 #define __Flx_SQR_KARATSUBA_LIMIT 264 #define __Flx_MUL_HALFMULII_LIMIT 9 #define __Flx_SQR_HALFSQRI_LIMIT 3 #define __Flx_MUL_MULII_LIMIT 6517 #define __Flx_SQR_SQRI_LIMIT 7265 #define __Flx_MUL_MULII2_LIMIT 5 #define __Flx_SQR_SQRI2_LIMIT 9 #define __Flx_INVMONTGOMERY_LIMIT 7426 #define __Flx_REM_MONTGOMERY_LIMIT 3407 #define __Flx_POW_MONTGOMERY_LIMIT 1015 #define __Flx_HALFGCD_LIMIT 74 #define __Flx_GCD_LIMIT 3041 #define __Flx_EXTGCD_LIMIT 280 #define __FpX_INVMONTGOMERY_LIMIT 407 #define __FpX_REM_MONTGOMERY_LIMIT 407 #define __FpX_POW_MONTGOMERY_LIMIT 176 #define __FpX_HALFGCD_LIMIT 115 #define __FpX_GCD_LIMIT 1292 #define __FpX_EXTGCD_LIMIT 222 #define __RgX_MUL_LIMIT 5 #define __RgX_SQR_LIMIT 27 #else #define __MULII_KARATSUBA_LIMIT 22 #define __SQRI_KARATSUBA_LIMIT 52 #define __MULII_FFT_LIMIT 1786 #define __SQRI_FFT_LIMIT 2442 #define __MULRR_MULII_LIMIT 136 #define __Fp_POW_REDC_LIMIT 99 #define __Fp_POW_BARRETT_LIMIT 107 #define __INVNEWTON_LIMIT 584 #define __DIVRR_GMP_LIMIT -1 #define __EXPNEWTON_LIMIT 67 #define __LOGAGM_LIMIT 49 #define __LOGAGMCX_LIMIT 66 #define __AGM_ATAN_LIMIT 166 #define __INVMOD_GMP_LIMIT -1 #define __Flx_MUL_KARATSUBA_LIMIT 48 #define __Flx_SQR_KARATSUBA_LIMIT 129 #define __Flx_MUL_HALFMULII_LIMIT 7 #define __Flx_SQR_HALFSQRI_LIMIT 5 #define __Flx_MUL_MULII_LIMIT 1517 #define __Flx_SQR_SQRI_LIMIT 2770 #define __Flx_MUL_MULII2_LIMIT 7337 #define __Flx_SQR_SQRI2_LIMIT 8511 #define __Flx_INVMONTGOMERY_LIMIT 1228 #define __Flx_REM_MONTGOMERY_LIMIT 835 #define __Flx_POW_MONTGOMERY_LIMIT 224 #define __Flx_HALFGCD_LIMIT 602 #define __Flx_GCD_LIMIT 9535 #define __Flx_EXTGCD_LIMIT 1127 #define __FpX_INVMONTGOMERY_LIMIT 427 #define __FpX_REM_MONTGOMERY_LIMIT 427 #define __FpX_POW_MONTGOMERY_LIMIT 188 #define __FpX_HALFGCD_LIMIT 173 #define __FpX_GCD_LIMIT 1719 #define __FpX_EXTGCD_LIMIT 282 #define __RgX_MUL_LIMIT 5 #define __RgX_SQR_LIMIT 22 #endif pari-2.5.5/src/kernel/none/asm0.h0000644000175000017500000000114712141040641015117 0ustar billbill/* $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. */ /* NOASM addll mulll bfffo divll */ pari-2.5.5/src/kernel/none/ratlift.c0000644000175000017500000002744712147140046015740 0ustar billbill#line 2 "../src/kernel/none/ratlift.c" /* $Id$ 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. */ /*========================================================== * ratlift(GEN x, GEN m, GEN *a, GEN *b, GEN amax, GEN bmax) *========================================================== * Reconstruct rational number from its residue x mod m * Given t_INT x, m, amax>=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 */ int ratlift(GEN x, GEN m, GEN amax, GEN bmax, GEN *a, GEN *b) { pari_sp av = avma; if ((typ(x) | typ(m) | typ(amax) | typ(bmax)) != t_INT) pari_err(arither1); if (signe(bmax) <= 0) pari_err(talker, "ratlift: bmax must be > 0, found\n\tbmax=%Ps\n", bmax); if (signe(amax) < 0) pari_err(talker, "ratilft: amax must be >= 0, found\n\tamax=%Ps\n", amax); /* check 2*amax*bmax < m */ if (cmpii(shifti(mulii(amax, bmax), 1), m) >= 0) pari_err(talker, "ratlift: must have 2*amax*bmax < m, found\n\tamax=%Ps\n\tbmax=%Ps\n\tm=%Ps\n", amax,bmax,m); /* we _could_ silently replace x with modii(x,m) instead of the following, * but let's leave this up to the caller */ if (signe(x) < 0 || cmpii(x,m) >= 0) pari_err(talker, "ratlift: must have 0 <= x < m, found\n\tx=%Ps\n\tm=%Ps\n", x,m); avma = av; return Fp_ratlift(x, m, amax, bmax, a, b); } 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(bugparier, "ratlift failed to catch d1 == 0\n"); return 0; /* NOTREACHED */ } pari-2.5.5/src/kernel/none/mp_indep.c0000644000175000017500000005117012147140046016054 0ustar billbill#line 2 "../src/kernel/none/mp_indep.c" /* $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. */ /* 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, lx; if (!signe(x)) return gen_0; ex = expo(x) + n; if (ex < 0) return gen_0; lx = lg(x); return trunc2nr_lg(x, lx, ex - bit_accuracy(lx) + 1); } /* x a t_REAL, x = i/2^e, i a t_INT */ GEN mantissa_real(GEN x, long *e) { long lx = lg(x); *e = bit_accuracy(lx)-1-expo(x); return trunc2nr_lg(x, lx, 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); 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); } #ifdef KARAMULR_VARIANT static GEN addshiftw(GEN x, GEN y, long d); static GEN karamulrr1(GEN y, GEN x, long ly, long lz) { long i, l, lz2 = (lz+2)>>1, lz3 = lz-lz2; GEN lo1, lo2, hi; hi = muliispec_mirror(x,y, lz2,lz2); i = lz2; while (i 0) hi = addiispec(hi+2,lo2+2, lgefint(hi)-2,l); return hi; } #endif /* set z <-- x*y, floating point multiplication. * 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 = expo(x) + expo(y); long i, j, lzz, p1; ulong garde; GEN y1; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; if (lz > MULRR_MULII_LIMIT) { pari_sp av = avma; #ifdef KARAMULR_VARIANT GEN hi = karamulrr1(y+2, x+2, lz+flag-2, lz-2); #else GEN hi = muliispec_mirror(y+2, x+2, lz+flag-2, lz-2); #endif garde = hi[lz]; if (hi[2] < 0) { ez++; for (i=2; i1 && z[i]==0); if (i == 1) { z[2] = (long)HIGHBIT; ez++; } } z[1] = evalsigne(sz)|evalexpo(ez); avma = av; return; } if (lz == 3) { if (flag) { (void)mulll(x[2],y[3]); garde = addmul(x[2],y[2]); } else garde = mulll(x[2],y[2]); if (hiremainder & HIGHBIT) { ez++; /* hiremainder < (2^BIL-1)^2 / 2^BIL, hence hiremainder+1 != 0 */ if (garde & HIGHBIT) hiremainder++; /* round properly */ } else { hiremainder = (hiremainder<<1) | (garde>>(BITS_IN_LONG-1)); if (garde & (HIGHBIT-1)) { hiremainder++; /* round properly */ if (!hiremainder) { hiremainder = HIGHBIT; ez++; } } } z[1] = evalsigne(sz) | evalexpo(ez); z[2] = hiremainder; return; } 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; if (z[2] < 0) ez++; else { shift_left(z,z,2,lzz, garde, 1); garde <<= 1; } if (garde & HIGHBIT) { /* round to nearest */ i = lz; do z[--i]++; while (i>2 && z[i]==0); if (z[i] == 0) { z[2] = (long)HIGHBIT; ez++; } } z[1] = evalsigne(sz) | evalexpo(ez); } GEN mulrr(GEN x, GEN y) { long flag, ly, lz, sx = signe(x), sy = signe(y); GEN z; if (!sx || !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); mulrrz_i(z, x,x, lz,0, 1); return z; } GEN mulir(GEN x, GEN y) { long sx = signe(x), sy, lz; GEN z; if (!sx) return mul0r(y); if (lgefint(x) == 3) { 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; lz = lg(y); z = cgetr(lz); mulrrz_i(z, itor(x,lz),y, lz,0, sx); avma = (pari_sp)z; return z; } /* 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(gdiver); 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(gdiver); 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(gdiver); 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(gdiver); 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(gdiver); 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(gdiver); 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 == ONLY_REM) { avma = av; return utoi(r); } if (z) *z = utoi(r); return q; } if (z == ONLY_REM) { avma = av; return utoi(r + labs(y)); } 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; q = sdivsi_rem(x,y,&r); if (r >= 0) { if (z == ONLY_REM) return utoi(r); if (z) *z = utoi(r); return stoi(q); } if (z == ONLY_REM) /* r += sign(y) * y, that is |y| */ return subiuspec(y+2,(ulong)-r, lgefint(y)-2); 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; } /* 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 usqrtsafe(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(talker, "NaN or Infinity in dbltor"); 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 (typ(x)==t_INT && !s) return 0.0; if (typ(x)!=t_REAL) pari_err(typeer,"rtodbl"); 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(overflower,"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(talker, "NaN or Infinity in dbltor"); 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 (typ(x)==t_INT && !s) return 0.0; if (typ(x)!=t_REAL) pari_err(typeer,"rtodbl"); 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(overflower,"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.5.5/src/kernel/none/cmp.c0000644000175000017500000000674012147140046015043 0ustar billbill#line 2 "../src/kernel/none/cmp.c" /* $Id$ 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 absi_cmp_lg and absi_equal_lg in mp.c*/ int equalii(GEN x, GEN y) { if ((x[1] & (LGBITS|SIGNBITS)) != (y[1] & (LGBITS|SIGNBITS))) return 0; return absi_equal_lg(x, y, lgefint(x)); } int cmpii(GEN x, GEN y) { const long sx = signe(x), sy = signe(y); long lx,ly; if (sxsy) return 1; if (!sx) return 0; lx=lgefint(x); ly=lgefint(y); if (lx>ly) return sx; if (lx0) return absi_cmp_lg(x, y, lx); else return -absi_cmp_lg(x, y, lx); } 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 (ily) return 1; if (lxey) return 1; if (ex (ulong)y[i])? 1: -1; if (lx>=ly) { while (i> 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.5.5/src/kernel/none/level1.h0000644000175000017500000007470612147140046015470 0ustar billbill#line 2 "../src/kernel/none/level1.h" /* $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. */ /* 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(overflower,"lg()"); return _evallg(x); } INLINE long evalvalp(long x) { long v = _evalvalp(x); if (v & ~VALPBITS) pari_err(overflower,"valp()"); return v; } INLINE long evalexpo(long x) { long v = _evalexpo(x); if (v & ~EXPOBITS) pari_err(overflower,"expo()"); 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(errpile); 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; } /* 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(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(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) { long lx; GEN y = cgetg_copy(x, &lx); while (--lx > 0) y[lx] = x[lx]; return y; } INLINE GEN icopy(GEN x) { register long lx = lgefint(x); GEN y = cgeti(lx); while (--lx > 0) y[lx] = x[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 absi(GEN x) { return mpabs(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(overflower,"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(overflower,"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(-bit_accuracy(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 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 subsi(long x, GEN y) { return addsi_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(gdiver); 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 udivui_rem(ulong x, GEN y, ulong *r) { long q, s = signe(y); LOCAL_HIREMAINDER; if (!s) pari_err(gdiver); 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; } INLINE long sdivsi_rem(long x, GEN y, long *r) { long q, s = signe(y); LOCAL_HIREMAINDER; if (!s) pari_err(gdiver); 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(gdiver); 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(gdiver); 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 = lg(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 (!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; 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_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) { LOCAL_HIREMAINDER; { register ulong x = mulll(a,b); (void)divll(x,p); } return hiremainder; } INLINE ulong Fl_sqr(ulong a, ulong p) { LOCAL_HIREMAINDER; { register ulong x = mulll(a,a); (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 addrs(GEN x, long s) { return addsr(s,x); } 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(overflower,"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); } /*******************************************************************/ /* */ /* 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(-bit_accuracy(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< 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.5.5/src/kernel/none/invmod.c0000644000175000017500000001235712147140046015561 0ustar billbill#line 2 "../src/kernel/none/invmod.c" /* $Id$ 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 (typ(a) != t_INT || typ(b) != t_INT) pari_err(arither1); 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.5.5/src/kernel/none/MakeLVL1.SH0000644000175000017500000000075512147140046015670 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 mp.c: \$(MP_C) cat \$(MP_C) > mp.c mp\$(_O): .headers mp.c \$(CC) -c \$(CFLAGS) \$(KERNELCFLAGS) \$(DLCFLAGS) \$(CPPFLAGS) -o mp\$(_O) mp.c EOT pari-2.5.5/src/kernel/none/bfffo.h0000644000175000017500000000373512141040641015346 0ustar billbill#line 2 "../src/kernel/none/bfffo.h" /* $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. */ #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.5.5/src/kernel/none/mpinl.c0000644000175000017500000000126112141040641015366 0ustar billbill/* $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. */ #define PARI_NO_PARIINL_H #define INLINE #define DISABLE_INLINE #include "pari.h" ulong hiremainder, overflow; pari-2.5.5/src/kernel/none/mp.c0000644000175000017500000014557312147140046014710 0ustar billbill#line 2 "../src/kernel/none/mp.c" /* $Id$ 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" int pari_kernel_init(void) { return 0; } /*nothing to do*/ /* 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 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 (l--; l>1; l--) if (a[l]--) break; l++; 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; 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]); for (i = -2; 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; 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 = subll(*--xd, *--yd); while (yd > y) *--zd = subllx(*--xd, *--yd); 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; } static void roundr_up_ip(GEN x, long l) { long i = l; for(;;) { if (++x[--i]) break; if (i == 2) { x[2] = (long)HIGHBIT; setexpo(x, expo(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); } } static GEN shifti_spec(GEN x, long lx, long n) { long ly, i, m, s = signe(x); GEN y; if (!s) return gen_0; if (!n) { y = cgeti(lx); y[1] = evalsigne(s) | evallgefint(lx); while (--lx > 1) y[lx]=x[lx]; return y; } if (n > 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(precer, "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(precer, "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 absi_cmp_lg(GEN x, GEN y, long l) { long i=2; while (i (ulong)y[i])? 1: -1; } INLINE int absi_equal_lg(GEN x, GEN y, long l) { long i = l-1; while (i>1 && x[i]==y[i]) i--; return i==1; } /***********************************************************************/ /** **/ /** 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; } GEN muliispec(GEN a, GEN b, long na, long nb); /*#define KARAMULR_VARIANT*/ #define muliispec_mirror muliispec /***********************************************************************/ /** **/ /** DIVISION **/ /** **/ /***********************************************************************/ ulong umodiu(GEN y, ulong x) { long sy=signe(y),ly,i; LOCAL_HIREMAINDER; if (!x) pari_err(gdiver); 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(gdiver); 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; } r = cgetr(3); r[1] = evalsigne(sx) | evalexpo(e); hiremainder=k; r[2]=divll(l,y[2]); 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 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 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; } GEN divri(GEN x, GEN y) { long lx, s = signe(y); pari_sp av; GEN z; if (!s) pari_err(gdiver); 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; pari_err(gdiver); } 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(bugparier,"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(bugparier,"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(gdiver); 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; } /********************************************************************/ /** **/ /** 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)); } /* 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); setexpo(t, expo(t)-1); avma = av; } affrr(t,y); setexpo(y, expo(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.5.5/src/kernel/none/gcdext.c0000644000175000017500000001406412147140046015540 0ustar billbill#line 2 "../src/kernel/none/gcdext.c" /* $Id$ 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 */ if (typ(a) != t_INT || typ(b) != t_INT) pari_err(arither1); 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.5.5/src/kernel/none/int.h0000644000175000017500000000261512141040641015052 0ustar billbill#line 2 "../src/kernel/none/int.h" /* $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. */ #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.5.5/src/kernel/x86_64/0000755000175000017500000000000012212611624014106 5ustar billbillpari-2.5.5/src/kernel/x86_64/asm0.h0000644000175000017500000000603612147140046015126 0ustar billbill#line 2 "../src/kernel/x86-64/asm0.h" /* $Id$ 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 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 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.5.5/src/kernel/ia64/0000755000175000017500000000000012212611624013713 5ustar billbillpari-2.5.5/src/kernel/ia64/asm0.h0000644000175000017500000000522012141040641014717 0ustar billbill#line 2 "../src/kernel/ia64/asm0.h" /* $Id$ 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.5.5/src/kernel/ia64/asm1.h0000644000175000017500000000406111636712103014731 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.5.5/src/kernel/sparcv8_super/0000755000175000017500000000000012212611624015754 5ustar billbillpari-2.5.5/src/kernel/sparcv8_super/asm0.h0000644000175000017500000000002211636712103016762 0ustar billbill/* NOASM divll */ pari-2.5.5/src/kernel/sparcv8_super/MakeLVL0.SH0000644000175000017500000000025211636712103017525 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.5.5/src/kernel/hppa64/0000755000175000017500000000000012212611624014252 5ustar billbillpari-2.5.5/src/kernel/hppa64/asm0.h0000644000175000017500000001001012141040641015247 0ustar billbill#line 2 "../src/kernel/hppa64/asm0.h" /* $Id$ 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.5.5/src/kernel/hppa/0000755000175000017500000000000012212611624014100 5ustar billbillpari-2.5.5/src/kernel/hppa/asm0.h0000644000175000017500000000542512141040641015113 0ustar billbill#line 2 "../src/kernel/hppa/asm0.h" /* $Id$ 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.5.5/src/kernel/ppc64/0000755000175000017500000000000012212611624014104 5ustar billbillpari-2.5.5/src/kernel/ppc64/asm0.h0000644000175000017500000000503312141040641015112 0ustar billbill/* $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. */ /* 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.5.5/src/kernel/gmp/0000755000175000017500000000000012212611624013733 5ustar billbillpari-2.5.5/src/kernel/gmp/tune.h0000644000175000017500000000607212147140046015066 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 15 #define __Fp_POW_REDC_LIMIT 6 #define __Fp_POW_BARRETT_LIMIT 83 #define __INVNEWTON_LIMIT 464 #define __DIVRR_GMP_LIMIT 4 #define __EXPNEWTON_LIMIT 66 #define __LOGAGM_LIMIT 10 #define __LOGAGMCX_LIMIT 33 #define __AGM_ATAN_LIMIT 60 #define __INVMOD_GMP_LIMIT 3 #define __Flx_MUL_KARATSUBA_LIMIT 155 #define __Flx_SQR_KARATSUBA_LIMIT 226 #define __Flx_MUL_MULII_LIMIT 6 #define __Flx_SQR_SQRI_LIMIT 5 #define __Flx_MUL_HALFMULII_LIMIT 6 #define __Flx_SQR_HALFSQRI_LIMIT 3 #define __Flx_MUL_MULII2_LIMIT 6 #define __Flx_SQR_SQRI2_LIMIT 5 #define __Flx_INVMONTGOMERY_LIMIT 804 #define __Flx_REM_MONTGOMERY_LIMIT 605 #define __Flx_POW_MONTGOMERY_LIMIT 216 #define __Flx_HALFGCD_LIMIT 94 #define __Flx_GCD_LIMIT 718 #define __Flx_EXTGCD_LIMIT 180 #define __FpX_INVMONTGOMERY_LIMIT 106 #define __FpX_REM_MONTGOMERY_LIMIT 93 #define __FpX_POW_MONTGOMERY_LIMIT 32 #define __FpX_HALFGCD_LIMIT 57 #define __FpX_GCD_LIMIT 354 #define __FpX_EXTGCD_LIMIT 79 #define __RgX_MUL_LIMIT 11 #define __RgX_SQR_LIMIT 46 #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 5 #define __Fp_POW_REDC_LIMIT 3 #define __Fp_POW_BARRETT_LIMIT 11 #define __INVNEWTON_LIMIT 330 #define __DIVRR_GMP_LIMIT 10 #define __EXPNEWTON_LIMIT 109 #define __LOGAGM_LIMIT 44 #define __LOGAGMCX_LIMIT 46 #define __AGM_ATAN_LIMIT 93 #define __INVMOD_GMP_LIMIT 3 #define __Flx_MUL_KARATSUBA_LIMIT 47 #define __Flx_SQR_KARATSUBA_LIMIT 105 #define __Flx_MUL_HALFMULII_LIMIT 5 #define __Flx_SQR_HALFSQRI_LIMIT 3 #define __Flx_MUL_MULII_LIMIT 5 #define __Flx_SQR_SQRI_LIMIT 5 #define __Flx_MUL_MULII2_LIMIT 61 #define __Flx_SQR_SQRI2_LIMIT 248 #define __Flx_INVMONTGOMERY_LIMIT 407 #define __Flx_REM_MONTGOMERY_LIMIT 200 #define __Flx_POW_MONTGOMERY_LIMIT 102 #define __Flx_HALFGCD_LIMIT 298 #define __Flx_GCD_LIMIT 1890 #define __Flx_EXTGCD_LIMIT 406 #define __FpX_INVMONTGOMERY_LIMIT 127 #define __FpX_REM_MONTGOMERY_LIMIT 127 #define __FpX_POW_MONTGOMERY_LIMIT 42 #define __FpX_HALFGCD_LIMIT 52 #define __FpX_GCD_LIMIT 377 #define __FpX_EXTGCD_LIMIT 73 #define __RgX_MUL_LIMIT 9 #define __RgX_SQR_LIMIT 42 #endif pari-2.5.5/src/kernel/gmp/gcd.c0000644000175000017500000000413712141040641014635 0ustar billbill#line 2 "../src/kernel/gmp/gcd.c" /* $Id$ 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.5.5/src/kernel/gmp/MakeLVL1.SH0000644000175000017500000000077412147140046015515 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 mp.c: \$(MP_C) cat \$(MP_C) > mp.c mp\$(_O): .headers mp.c \$(CC) -c \$(CFLAGS) \$(KERNELCFLAGS) \$(DLCFLAGS) \$(CPPFLAGS) \$(GMPINCLUDE) -o mp\$(_O) mp.c EOT pari-2.5.5/src/kernel/gmp/mp.c0000644000175000017500000007667712147140046014544 0ustar billbill#line 2 "../src/kernel/gmp/mp.c" /* $Id$ 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 *gmp_realloc(void *ptr, size_t old_size, size_t new_size) { (void)old_size; return (void *) pari_realloc(ptr,new_size); } static void gmp_free(void *ptr, size_t old_size){ (void)old_size; pari_free(ptr); } int pari_kernel_init(void) { /* Use pari_malloc instead of malloc */ mp_set_memory_functions((void *(*)(size_t)) pari_malloc, gmp_realloc, gmp_free); return 0; } #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 (++x[--i]) break; if (i == 2) { x[2] = HIGHBIT; setexpo(x, expo(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); } } GEN shifti(GEN x, long n) { const long s=signe(x); long lz,lx,m; GEN z; if (!s) return gen_0; if (!n) return icopy(x); lx = lgefint(x); if (n > 0) { long d = dvmdsBIL(n, &m); long i; lz = lx + d + (m!=0); z = cgeti(lz); 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(precer, "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(precer, "floorr (precision loss in truncation)"); y = cgeti(d+1); if (++m == BITS_IN_LONG) { for (i=2; i 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=ny. This lets garbage on the stack. This handle squares correctly (mpn_mul is optimized for squares). */ INLINE GEN muliispec_mirror(GEN x, GEN y, long nx, long ny) { GEN cx=new_chunk(nx),cy; GEN z; xmpn_mirrorcopy((mp_limb_t *)cx,(mp_limb_t *)x,nx); if (x==y) cy=cx; /*If nx 0)? hi: x - hi; } /* return |y| \/ x */ GEN diviu_rem(GEN y, ulong x, ulong *rem) { long ly; GEN z; if (!x) pari_err(gdiver); 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(gdiver); 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(gdiver); 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(gdiver); 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(gdiver); 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; } r = cgetr(3); r[1] = evalsigne(sx) | evalexpo(e); hiremainder=k; r[2]=divll(l,y[2]); 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 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 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(gdiver); } 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(bugparier,"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(bugparier,"red_montgomery"); } #endif avma = (pari_sp)Td; return Td; } /* EXACT INTEGER DIVISION */ #if 1 /* use undocumented GMP interface */ 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(gdiver); 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 /********************************************************************/ /** **/ /** 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 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); mpn_mul_n(LIMBS(zd), (mp_limb_t *)x, (mp_limb_t *)x, nx); if (zd[lz-1]==0) lz--; zd[1] = evalsigne(1) | evallgefint(lz); return zd; } /* x % (2^n), assuming n >= 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 *) trunc2nr_lg(a,l+2,-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 lu, l, su, sa = signe(a), lb,lna; 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 */ if (typ(a) != t_INT || typ(b) != t_INT) pari_err(arither1); 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,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.5.5/src/kernel/gmp/int.h0000644000175000017500000000257312141040641014701 0ustar billbill#line 2 "../src/kernel/gmp/int.h" /* $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. */ #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.5.5/src/kernel/ix86/0000755000175000017500000000000012212611624013746 5ustar billbillpari-2.5.5/src/kernel/ix86/asm0.h0000644000175000017500000000640212147140046014763 0ustar billbill#line 2 "../src/kernel/ix86/asm0.h" /* $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. */ /* 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. */ /* 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 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 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.5.5/src/kernel/m68k/0000755000175000017500000000000012212611624013735 5ustar billbillpari-2.5.5/src/kernel/m68k/asm0.h0000644000175000017500000001201712141040641014743 0ustar billbill#line 2 "../src/kernel/m68k/asm0.h" /* $Id$ 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.5.5/src/kernel/README0000644000175000017500000000267611636712103014046 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.5.5/src/kernel/alpha/0000755000175000017500000000000012212611624014235 5ustar billbillpari-2.5.5/src/kernel/alpha/asm0.h0000644000175000017500000000500312141040641015240 0ustar billbill/* $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. */ /* 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.5.5/src/kernel/alpha/asm1.h0000644000175000017500000000706412147140046015260 0ustar billbill/* $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. */ /* This file is a slight adaptation of source code extracted from gmp-3.1.1 (from T. Granlund), files longlong.h and gmp-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.5.5/src/kernel/sparcv8_micro/0000755000175000017500000000000012212611624015727 5ustar billbillpari-2.5.5/src/kernel/sparcv8_micro/asm0.h0000644000175000017500000000171212141040641016735 0ustar billbill/* $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. */ /* 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.5.5/src/kernel/sparcv8_micro/asm0-common.h0000644000175000017500000000477112141040641020233 0ustar billbill/* $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. */ /* 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.5.5/src/kernel/sparcv8_micro/MakeLVL0.SH0000644000175000017500000000020411636712103017475 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.5.5/src/whatnow0000644000175000017500000003214512147140047013312 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 _.w _.zk _.zkst _/=_ _/_ _<<=_ _<<_ _<=_ _<_ _==_ _=_ _>=_ _>>=_ _>>_ _>_ _\\/=_ _\\/_ _\\=_ _\\_ _^_ _^s __ _derivfun _eval_mnemonic _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)=ellpow(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)=polroots(x,1); 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.5.5/src/graph/0000755000175000017500000000000012212611624012771 5ustar billbillpari-2.5.5/src/graph/plotWin32.c0000644000175000017500000000631512147140046014745 0ustar billbill/* $Id$ 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 "pari.h" #include "paripriv.h" #include "rect.h" #include #include 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, 3)); } 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) { 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); ysml = ybig = 0.; 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; jz = 3 - DTOL(ysml*dyj); z = PICTZERO(jz); 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); free((void*)rgb_colors); } if (pari_colormap) free(pari_colormap); if (pari_graphcolors) free(pari_graphcolors); } static PariRect * check_rect(long ne) { if (ne >= 0 && ne < NUMRECT) return rectgraph[ne]; pari_err(talker, "incorrect rectwindow number in graphic function (%ld not in [0, %ld])", ne, NUMRECT-1); return NULL; /*not reached*/ } static PariRect * check_rect_init(long ne) { PariRect *e = check_rect(ne); if (!RHead(e)) pari_err(talker,"you must initialize the rectwindow first"); 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(0); return *dft - 1; } if (typ(x) != t_INT) pari_err(typeer, "initrect"); return itos(x); } void initrect_gen(long ne, GEN x, GEN y, long flag) { 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)); } 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 || y<=1) pari_err(talker,"incorrect dimensions in initrect"); 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) { check_rect(ne); if (c < 1 || c >= lg(pari_colormap)-1) pari_err(talker,"This is not a valid color"); 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 || ty == t_MAT || lg(listy) != lx) pari_err(typeer,"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; else 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; else if (y > f->ybig) f->ybig=y; } /* 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 tx=typ(data), ty, nl=lg(data)-1, lx1,lx; register long i,j,u,v; long param=(flags & (PLOT_PARAMETRIC|PLOT_COMPLEX)); long cplx=(flags & PLOT_COMPLEX); GEN x,y; if (! is_vec_t(tx)) pari_err(typeer,"gtodblList"); if (!nl) return NULL; lx1 = lg(data[1]); if (nl == 1 && !cplx) pari_err(talker,"single vector in gtodblList"); /* Allocate memory, then convert coord. to double */ l = (dblPointList*) pari_malloc((cplx ? 2*nl:nl)*sizeof(dblPointList)); for (i=0; i= l[0].nb) { pari_free(l); return NULL; } xsml = xbig = l[i ].d[0]; ysml = ybig = l[i+1].d[0]; for (i=0; i < l[0].nb; i+=2) { u = i+1; for (j=0; j < l[u].nb; j++) { if (l[i].d[j] < xsml) xsml = l[i].d[j]; else if (l[i].d[j] > xbig) xbig = l[i].d[j]; if (l[u].d[j] < ysml) ysml = l[u].d[j]; else if (l[u].d[j] > ybig) ybig = l[u].d[j]; } } } else { if (!l[0].nb) { pari_free(l); return NULL; } 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++) { if (l[0].d[j] < xsml) xsml = l[0].d[j]; else if (l[0].d[j] > xbig) xbig = l[0].d[j]; } for (i=1; i <= l[0].nb; i++) for (j=0; j < l[i].nb; j++) { if (l[i].d[j] < ysml) ysml = l[i].d[j]; else if (l[i].d[j] > ybig) ybig = l[i].d[j]; } } l[0].xsml = xsml; l[0].xbig = xbig; l[0].ysml = ysml; l[0].ybig = ybig; return l; } 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 = addrr(xleft,xright); setexpo(xx, expo(xx)-1); 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(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==PARAMR_MAXDEPTH) return; tt = addrr(tleft,tright); setexpo(tt, expo(tt)-1); p1 = READ_EXPR(code,tt); if (typ(p1)==t_VEC) { if (lg(p1) == 2) { /* cplx */ p1 = gel(p1,1); xx = gtodouble(real_i(p1)); yy = gtodouble(imag_i(p1)); } else { xx = gtodouble(gel(p1,1)); yy = gtodouble(gel(p1,2)); } } else { xx = gtodouble(real_i(p1)); yy = gtodouble(imag_i(p1)); } if (dx && dy && fabs(xleft+xright-2*xx) < dx*RECUR_PREC && fabs(yleft+yright-2*yy) < dy*RECUR_PREC) return; param_recursion(pl,code, tleft,xleft,yleft, tt,xx,yy, depth+1); Appendx(&pl[0],&pl[0],xx); Appendy(&pl[0],&pl[1],yy); param_recursion(pl,code, tt,xx,yy, tright,xright,yright, depth+1); avma = av; } /* Pure graphing. If testpoints is 0, it is set to the default. * Returns a dblPointList of (absolute) coordinates. */ static dblPointList * rectplothin(GEN a, GEN b, GEN code, long prec, ulong flags, long testpoints) { long single_c; long param=flags & (PLOT_PARAMETRIC|PLOT_COMPLEX); long recur=flags & PLOT_RECURSIVE; long cplx=flags & PLOT_COMPLEX; GEN t,dx,x; dblPointList *pl; long tx, i, j, sig, nc, nl, nbpoints; pari_sp av = avma, av2; double xsml,xbig,ysml,ybig,fx,fy; if (!testpoints) { if (recur) testpoints = RECUR_NUMPOINTS; else testpoints = param? PARAM_NUMPOINTS : PLOTH_NUMPOINTS; } if (recur) nbpoints = testpoints << (param? PARAMR_MAXDEPTH : RECUR_MAXDEPTH); else nbpoints = testpoints; sig = gcmp(b,a); if (!sig) return NULL; if (sig<0) swap(a, b); dx = divru(gtofp(gsub(b,a),prec), testpoints-1); x = gtofp(a, prec); if (typ(code) == t_CLOSURE) push_lex(x, code); av2=avma; t=READ_EXPR(code,x); tx=typ(t); /* nc = nb of curves; nl = nb of coord. lists */ if (!is_matvec_t(tx) && !cplx) { xsml = gtodouble(a); xbig = gtodouble(b); ysml = ybig = gtodouble(t); nc=1; nl=2; if (param) pari_warn(warner,"flag PLOT_PARAMETRIC ignored"); single_c=1; param=0; } else { if (tx != t_VEC) { if (!cplx) pari_err(talker,"not a row vector in ploth"); nc = nl = 1; } else { nl = lg(t)-1; if (!nl) { avma=av; return NULL; } if (param && !cplx) { nc = nl/2; if (odd(nl)) pari_err(talker, "parametric plot requires an even number of components"); } else { nc = nl; if (!cplx) nl++; } } if (recur && nc > 1) pari_err(talker,"multi-curves cannot be plot recursively"); single_c=0; if (param) { if (cplx) { GEN z = (typ(t) == t_VEC)? gel(t,1): t; xbig = xsml = gtodouble(real_i(z)); ybig = ysml = gtodouble(imag_i(z)); } else { xbig = xsml = gtodouble(gel(t,1)); ybig = ysml = gtodouble(gel(t,2)); } for (i=2+!cplx; i<=nl; i++) { if (cplx) { GEN z = gel(t,i); fx = gtodouble(real_i(z)); fy = gtodouble(imag_i(z)); } else { fx = gtodouble(gel(t,i)); i++; fy = gtodouble(gel(t,i)); } if (xsml>fx) xsml=fx; else if (xbigfy) ysml=fy; else if (ybig0) 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. * * Additional flags: PLOT_NO_AXE_X, PLOT_NO_AXE_Y, PLOT_NO_FRAME. */ static GEN rectplothrawin(long stringrect, long drawrect, dblPointList *data, long flags, PARI_plot *WW) { GEN res; dblPointList y,x; double xsml,xbig,ysml,ybig,tmp; long ltype, max_graphcolors; long param = flags & (PLOT_PARAMETRIC|PLOT_COMPLEX); pari_sp ltop = avma; long i,nc,nbpoints, w[2], wx[2], wy[2]; if (!data) return cgetg(1,t_VEC); w[0] = stringrect; w[1] = drawrect; x = data[0]; nc = x.nb; xsml = x.xsml; xbig = x.xbig; ysml = x.ysml; ybig = x.ybig; if (xbig-xsml < 1.e-9) { tmp=fabs(xsml)/10; if (!tmp) tmp=0.1; xbig+=tmp; xsml-=tmp; } if (ybig-ysml < 1.e-9) { tmp=fabs(ysml)/10; if (!tmp) tmp=0.1; ybig+=tmp; ysml-=tmp; } if (WW) { /* no rectwindow supplied ==> ps or screen output */ char c1[16],c2[16],c3[16],c4[16]; PARI_plot W = *WW; long lm = W.fwidth*10; /* left margin */ long rm = W.hunit-1; /* right margin */ long tm = W.vunit-1; /* top margin */ long bm = W.vunit+W.fheight-1; /* bottom margin */ long is = W.width - (lm+rm); long js = W.height - (tm+bm); wx[0]=wy[0]=0; wx[1]=lm; wy[1]=tm; /* Window size (W.width x W.height) is given in pixels, and * correct pixels are 0..W.width-1. * On the other hand, rect functions work with windows whose pixel * range is [0,width]. */ initrect(stringrect, W.width-1, W.height-1); if (drawrect != stringrect) initrect(drawrect, is-1, js-1); /* draw labels on stringrect */ sprintf(c1,"%.5g",ybig); sprintf(c2,"%.5g",ysml); sprintf(c3,"%.5g",xsml); sprintf(c4,"%.5g",xbig); rectlinetype(stringrect,-2); /* Frame */ rectcolor(stringrect, DEFAULT_COLOR); put_string(stringrect, lm, 0, c1, RoSTdirRIGHT | RoSTdirHGAP | RoSTdirTOP); put_string(stringrect, lm, W.height - bm, c2, RoSTdirRIGHT | RoSTdirHGAP | RoSTdirVGAP); put_string(stringrect, lm, W.height - bm, c3, RoSTdirLEFT | RoSTdirTOP); put_string(stringrect, W.width - rm - 1, W.height - bm, c4, RoSTdirRIGHT | RoSTdirTOP); } RHasGraph(check_rect(drawrect)) = 1; if (!(flags & PLOT_NO_RESCALE)) rectscale0(drawrect, xsml, xbig, ysml, ybig); if (!(flags & PLOT_NO_FRAME)) { int do_double = (flags & PLOT_NODOUBLETICK) ? TICKS_NODOUBLE : 0; PARI_plot *pl = WW; if (!pl) { PARI_get_plot(0); pl = &pari_plot; } rectlinetype(drawrect, -2); /* Frame. */ current_color[drawrect] = DEFAULT_COLOR; rectmove0(drawrect,xsml,ysml,0); rectbox0(drawrect,xbig,ybig,0); if (!(flags & PLOT_NO_TICK_X)) { rectticks(pl, drawrect, xsml, ysml, xbig, ysml, xsml, xbig, TICKS_CLOCKW | do_double); rectticks(pl, drawrect, xbig, ybig, xsml, ybig, xbig, xsml, TICKS_CLOCKW | do_double); } if (!(flags & PLOT_NO_TICK_Y)) { rectticks(pl, drawrect, xbig, ysml, xbig, ybig, ysml, ybig, TICKS_CLOCKW | do_double); rectticks(pl, drawrect, xsml, ybig, xsml, ysml, ybig, ysml, TICKS_CLOCKW | do_double); } } if (!(flags & PLOT_NO_AXE_Y) && (xsml<=0 && xbig >=0)) { rectlinetype(drawrect, -1); /* Axes. */ current_color[drawrect] = AXIS_COLOR; rectmove0(drawrect,0.0,ysml,0); rectline0(drawrect,0.0,ybig,0); } if (!(flags & PLOT_NO_AXE_X) && (ysml<=0 && ybig >=0)) { rectlinetype(drawrect, -1); /* Axes. */ current_color[drawrect] = AXIS_COLOR; rectmove0(drawrect,xsml,0.0,0); rectline0(drawrect,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[drawrect] = 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(drawrect, rectpoint_itype + ltype); /* Graphs */ rectpointtype(drawrect,rectpoint_itype + ltype); /* Graphs */ rectpoints0(drawrect,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(drawrect,x.d,y.d,nbpoints,flags); rectline_itype = old; } else { rectlinetype(drawrect, rectline_itype + ltype); /* Graphs */ rectlines0(drawrect,x.d,y.d,nbpoints,0); } } for (i--; i>=0; i--) pari_free(data[i].d); pari_free(data); if (WW) { if (flags & PLOT_POSTSCRIPT) postdraw0(w,wx,wy,2, 0); else rectdraw0(w,wx,wy,2); killrect(drawrect); if (stringrect != drawrect) killrect(stringrect); } avma=ltop; res = cgetg(5,t_VEC); gel(res,1) = dbltor(xsml); gel(res,2) = dbltor(xbig); gel(res,3) = dbltor(ysml); gel(res,4) = dbltor(ybig); return res; } /*************************************************************************/ /* */ /* HI-RES FUNCTIONS */ /* */ /*************************************************************************/ GEN rectploth(long drawrect,GEN a,GEN b,GEN code, long prec,ulong flags,long testpoints) { dblPointList *pl=rectplothin(a,b, code, prec, flags,testpoints); return rectplothrawin(0,drawrect, pl, flags,NULL); } GEN rectplothraw(long drawrect, GEN data, long flags) { dblPointList *pl=gtodblList(data,flags); return rectplothrawin(0,drawrect,pl,flags,NULL); } static PARI_plot* init_output(long flags) { if (flags & PLOT_POSTSCRIPT) { PARI_get_psplot(); return &pari_psplot; } else { PARI_get_plot(0); return &pari_plot; } } static GEN ploth0(GEN a,GEN b,GEN code, long prec,ulong flags,long testpoints) { PARI_plot *output = init_output(flags); dblPointList *pl=rectplothin(a,b, code, prec, flags,testpoints); return rectplothrawin(STRINGRECT,DRAWRECT, pl, flags, output); } static GEN plothraw0(GEN listx, GEN listy, long flags) { PARI_plot *output = init_output(flags); long data[] = {evaltyp(t_VEC) | _evallg(3), 0, 0}; dblPointList *pl; gel(data,1) = listx; gel(data,2) = listy; pl=gtodblList(data,PLOT_PARAMETRIC|(flags&PLOT_COMPLEX)); if (!pl) return cgetg(1,t_VEC); return rectplothrawin(STRINGRECT,DRAWRECT,pl,flags | PLOT_PARAMETRIC,output); } GEN plothraw(GEN listx, GEN listy, long flags) { if (flags <= 1) flags = flags? 0: PLOT_POINTS; return plothraw0(listx, listy, flags); } GEN ploth(GEN a, GEN b, GEN code, long prec,long flags,long numpoints) { return ploth0(a,b,code,prec,flags,numpoints); } GEN ploth2(GEN a, GEN b, GEN code, long prec) { return ploth0(a,b,code,prec,PLOT_PARAMETRIC,0); } GEN plothmult(GEN a, GEN b, GEN code, long prec) { return ploth0(a,b,code,prec,0,0); } GEN postplothraw(GEN listx, GEN listy, long flags) { return plothraw0(listx, listy, flags? PLOT_POSTSCRIPT : PLOT_POINTS|PLOT_POSTSCRIPT); } GEN postploth(GEN a, GEN b, GEN code, long prec,long flags, long numpoints) { return ploth0(a,b,code,prec,flags|PLOT_POSTSCRIPT, numpoints); } GEN postploth2(GEN a, GEN b, GEN code, long prec, long numpoints) { return ploth0(a,b,code,prec, PLOT_PARAMETRIC|PLOT_POSTSCRIPT,numpoints); } GEN plothsizes(void) { return plothsizes_flag(0); } GEN plothsizes_flag(long flag) { GEN vect = cgetg(1+6,t_VEC); PARI_get_plot(0); 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(talker,"not a vector in rectdraw"); n = lg(list)-1; if (!n) return; if (n%3) pari_err(talker,"incorrect number of components in 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(0); 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; ipl->hunit, fheight = eng->pl->fheight; long vgapsize = eng->pl->vunit, fwidth = eng->pl->fwidth; for(i=0; isc(data,RoCol(R)); eng->pt(data, DTOL((RoPTx(R)+x0)*xs), DTOL((RoPTy(R)+y0)*ys)); break; case ROt_LN: eng->sc(data,RoCol(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,RoCol(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,RoCol(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,RoCol(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,RoCol(R)); eng->st(data, x, y, text, l); break; } default: break; } } } } /*************************************************************************/ /* */ /* RGB COLORS */ /* */ /*************************************************************************/ #if 0 /* 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("(void*)0x%02x%02x%02x", split(/\s+/, $hex)); $name = lc($name); next if ($done{$name}); $done{$name} = 1; print "{(void*)\"$name\", $hex},\n"; } #endif static hashentry col_list[] = { {(void*)"snow", (void*)0xfffafa}, {(void*)"ghostwhite", (void*)0xf8f8ff}, {(void*)"whitesmoke", (void*)0xf5f5f5}, {(void*)"gainsboro", (void*)0xdcdcdc}, {(void*)"floralwhite", (void*)0xfffaf0}, {(void*)"oldlace", (void*)0xfdf5e6}, {(void*)"linen", (void*)0xfaf0e6}, {(void*)"antiquewhite", (void*)0xfaebd7}, {(void*)"papayawhip", (void*)0xffefd5}, {(void*)"blanchedalmond", (void*)0xffebcd}, {(void*)"bisque", (void*)0xffe4c4}, {(void*)"peachpuff", (void*)0xffdab9}, {(void*)"navajowhite", (void*)0xffdead}, {(void*)"moccasin", (void*)0xffe4b5}, {(void*)"cornsilk", (void*)0xfff8dc}, {(void*)"ivory", (void*)0xfffff0}, {(void*)"lemonchiffon", (void*)0xfffacd}, {(void*)"seashell", (void*)0xfff5ee}, {(void*)"honeydew", (void*)0xf0fff0}, {(void*)"mintcream", (void*)0xf5fffa}, {(void*)"azure", (void*)0xf0ffff}, {(void*)"aliceblue", (void*)0xf0f8ff}, {(void*)"lavender", (void*)0xe6e6fa}, {(void*)"lavenderblush", (void*)0xfff0f5}, {(void*)"mistyrose", (void*)0xffe4e1}, {(void*)"white", (void*)0xffffff}, {(void*)"black", (void*)0x000000}, {(void*)"darkslategray", (void*)0x2f4f4f}, {(void*)"darkslategrey", (void*)0x2f4f4f}, {(void*)"dimgray", (void*)0x696969}, {(void*)"dimgrey", (void*)0x696969}, {(void*)"slategray", (void*)0x708090}, {(void*)"slategrey", (void*)0x708090}, {(void*)"lightslategray", (void*)0x778899}, {(void*)"lightslategrey", (void*)0x778899}, {(void*)"gray", (void*)0xbebebe}, {(void*)"grey", (void*)0xbebebe}, {(void*)"lightgrey", (void*)0xd3d3d3}, {(void*)"lightgray", (void*)0xd3d3d3}, {(void*)"midnightblue", (void*)0x191970}, {(void*)"navy", (void*)0x000080}, {(void*)"navyblue", (void*)0x000080}, {(void*)"cornflowerblue", (void*)0x6495ed}, {(void*)"darkslateblue", (void*)0x483d8b}, {(void*)"slateblue", (void*)0x6a5acd}, {(void*)"mediumslateblue", (void*)0x7b68ee}, {(void*)"lightslateblue", (void*)0x8470ff}, {(void*)"mediumblue", (void*)0x0000cd}, {(void*)"royalblue", (void*)0x4169e1}, {(void*)"blue", (void*)0x0000ff}, {(void*)"dodgerblue", (void*)0x1e90ff}, {(void*)"deepskyblue", (void*)0x00bfff}, {(void*)"skyblue", (void*)0x87ceeb}, {(void*)"lightskyblue", (void*)0x87cefa}, {(void*)"steelblue", (void*)0x4682b4}, {(void*)"lightsteelblue", (void*)0xb0c4de}, {(void*)"lightblue", (void*)0xadd8e6}, {(void*)"powderblue", (void*)0xb0e0e6}, {(void*)"paleturquoise", (void*)0xafeeee}, {(void*)"darkturquoise", (void*)0x00ced1}, {(void*)"mediumturquoise", (void*)0x48d1cc}, {(void*)"turquoise", (void*)0x40e0d0}, {(void*)"cyan", (void*)0x00ffff}, {(void*)"lightcyan", (void*)0xe0ffff}, {(void*)"cadetblue", (void*)0x5f9ea0}, {(void*)"mediumaquamarine", (void*)0x66cdaa}, {(void*)"aquamarine", (void*)0x7fffd4}, {(void*)"darkgreen", (void*)0x006400}, {(void*)"darkolivegreen", (void*)0x556b2f}, {(void*)"darkseagreen", (void*)0x8fbc8f}, {(void*)"seagreen", (void*)0x2e8b57}, {(void*)"mediumseagreen", (void*)0x3cb371}, {(void*)"lightseagreen", (void*)0x20b2aa}, {(void*)"palegreen", (void*)0x98fb98}, {(void*)"springgreen", (void*)0x00ff7f}, {(void*)"lawngreen", (void*)0x7cfc00}, {(void*)"green", (void*)0x00ff00}, {(void*)"chartreuse", (void*)0x7fff00}, {(void*)"mediumspringgreen", (void*)0x00fa9a}, {(void*)"greenyellow", (void*)0xadff2f}, {(void*)"limegreen", (void*)0x32cd32}, {(void*)"yellowgreen", (void*)0x9acd32}, {(void*)"forestgreen", (void*)0x228b22}, {(void*)"olivedrab", (void*)0x6b8e23}, {(void*)"darkkhaki", (void*)0xbdb76b}, {(void*)"khaki", (void*)0xf0e68c}, {(void*)"palegoldenrod", (void*)0xeee8aa}, {(void*)"lightgoldenrodyellow", (void*)0xfafad2}, {(void*)"lightyellow", (void*)0xffffe0}, {(void*)"yellow", (void*)0xffff00}, {(void*)"gold", (void*)0xffd700}, {(void*)"lightgoldenrod", (void*)0xeedd82}, {(void*)"goldenrod", (void*)0xdaa520}, {(void*)"darkgoldenrod", (void*)0xb8860b}, {(void*)"rosybrown", (void*)0xbc8f8f}, {(void*)"indianred", (void*)0xcd5c5c}, {(void*)"saddlebrown", (void*)0x8b4513}, {(void*)"sienna", (void*)0xa0522d}, {(void*)"peru", (void*)0xcd853f}, {(void*)"burlywood", (void*)0xdeb887}, {(void*)"beige", (void*)0xf5f5dc}, {(void*)"wheat", (void*)0xf5deb3}, {(void*)"sandybrown", (void*)0xf4a460}, {(void*)"tan", (void*)0xd2b48c}, {(void*)"chocolate", (void*)0xd2691e}, {(void*)"firebrick", (void*)0xb22222}, {(void*)"brown", (void*)0xa52a2a}, {(void*)"darksalmon", (void*)0xe9967a}, {(void*)"salmon", (void*)0xfa8072}, {(void*)"lightsalmon", (void*)0xffa07a}, {(void*)"orange", (void*)0xffa500}, {(void*)"darkorange", (void*)0xff8c00}, {(void*)"coral", (void*)0xff7f50}, {(void*)"lightcoral", (void*)0xf08080}, {(void*)"tomato", (void*)0xff6347}, {(void*)"orangered", (void*)0xff4500}, {(void*)"red", (void*)0xff0000}, {(void*)"hotpink", (void*)0xff69b4}, {(void*)"deeppink", (void*)0xff1493}, {(void*)"pink", (void*)0xffc0cb}, {(void*)"lightpink", (void*)0xffb6c1}, {(void*)"palevioletred", (void*)0xdb7093}, {(void*)"maroon", (void*)0xb03060}, {(void*)"mediumvioletred", (void*)0xc71585}, {(void*)"violetred", (void*)0xd02090}, {(void*)"magenta", (void*)0xff00ff}, {(void*)"violet", (void*)0xee82ee}, {(void*)"plum", (void*)0xdda0dd}, {(void*)"orchid", (void*)0xda70d6}, {(void*)"mediumorchid", (void*)0xba55d3}, {(void*)"darkorchid", (void*)0x9932cc}, {(void*)"darkviolet", (void*)0x9400d3}, {(void*)"blueviolet", (void*)0x8a2be2}, {(void*)"purple", (void*)0xa020f0}, {(void*)"mediumpurple", (void*)0x9370db}, {(void*)"thistle", (void*)0xd8bfd8}, {(void*)"snow1", (void*)0xfffafa}, {(void*)"snow2", (void*)0xeee9e9}, {(void*)"snow3", (void*)0xcdc9c9}, {(void*)"snow4", (void*)0x8b8989}, {(void*)"seashell1", (void*)0xfff5ee}, {(void*)"seashell2", (void*)0xeee5de}, {(void*)"seashell3", (void*)0xcdc5bf}, {(void*)"seashell4", (void*)0x8b8682}, {(void*)"antiquewhite1", (void*)0xffefdb}, {(void*)"antiquewhite2", (void*)0xeedfcc}, {(void*)"antiquewhite3", (void*)0xcdc0b0}, {(void*)"antiquewhite4", (void*)0x8b8378}, {(void*)"bisque1", (void*)0xffe4c4}, {(void*)"bisque2", (void*)0xeed5b7}, {(void*)"bisque3", (void*)0xcdb79e}, {(void*)"bisque4", (void*)0x8b7d6b}, {(void*)"peachpuff1", (void*)0xffdab9}, {(void*)"peachpuff2", (void*)0xeecbad}, {(void*)"peachpuff3", (void*)0xcdaf95}, {(void*)"peachpuff4", (void*)0x8b7765}, {(void*)"navajowhite1", (void*)0xffdead}, {(void*)"navajowhite2", (void*)0xeecfa1}, {(void*)"navajowhite3", (void*)0xcdb38b}, {(void*)"navajowhite4", (void*)0x8b795e}, {(void*)"lemonchiffon1", (void*)0xfffacd}, {(void*)"lemonchiffon2", (void*)0xeee9bf}, {(void*)"lemonchiffon3", (void*)0xcdc9a5}, {(void*)"lemonchiffon4", (void*)0x8b8970}, {(void*)"cornsilk1", (void*)0xfff8dc}, {(void*)"cornsilk2", (void*)0xeee8cd}, {(void*)"cornsilk3", (void*)0xcdc8b1}, {(void*)"cornsilk4", (void*)0x8b8878}, {(void*)"ivory1", (void*)0xfffff0}, {(void*)"ivory2", (void*)0xeeeee0}, {(void*)"ivory3", (void*)0xcdcdc1}, {(void*)"ivory4", (void*)0x8b8b83}, {(void*)"honeydew1", (void*)0xf0fff0}, {(void*)"honeydew2", (void*)0xe0eee0}, {(void*)"honeydew3", (void*)0xc1cdc1}, {(void*)"honeydew4", (void*)0x838b83}, {(void*)"lavenderblush1", (void*)0xfff0f5}, {(void*)"lavenderblush2", (void*)0xeee0e5}, {(void*)"lavenderblush3", (void*)0xcdc1c5}, {(void*)"lavenderblush4", (void*)0x8b8386}, {(void*)"mistyrose1", (void*)0xffe4e1}, {(void*)"mistyrose2", (void*)0xeed5d2}, {(void*)"mistyrose3", (void*)0xcdb7b5}, {(void*)"mistyrose4", (void*)0x8b7d7b}, {(void*)"azure1", (void*)0xf0ffff}, {(void*)"azure2", (void*)0xe0eeee}, {(void*)"azure3", (void*)0xc1cdcd}, {(void*)"azure4", (void*)0x838b8b}, {(void*)"slateblue1", (void*)0x836fff}, {(void*)"slateblue2", (void*)0x7a67ee}, {(void*)"slateblue3", (void*)0x6959cd}, {(void*)"slateblue4", (void*)0x473c8b}, {(void*)"royalblue1", (void*)0x4876ff}, {(void*)"royalblue2", (void*)0x436eee}, {(void*)"royalblue3", (void*)0x3a5fcd}, {(void*)"royalblue4", (void*)0x27408b}, {(void*)"blue1", (void*)0x0000ff}, {(void*)"blue2", (void*)0x0000ee}, {(void*)"blue3", (void*)0x0000cd}, {(void*)"blue4", (void*)0x00008b}, {(void*)"dodgerblue1", (void*)0x1e90ff}, {(void*)"dodgerblue2", (void*)0x1c86ee}, {(void*)"dodgerblue3", (void*)0x1874cd}, {(void*)"dodgerblue4", (void*)0x104e8b}, {(void*)"steelblue1", (void*)0x63b8ff}, {(void*)"steelblue2", (void*)0x5cacee}, {(void*)"steelblue3", (void*)0x4f94cd}, {(void*)"steelblue4", (void*)0x36648b}, {(void*)"deepskyblue1", (void*)0x00bfff}, {(void*)"deepskyblue2", (void*)0x00b2ee}, {(void*)"deepskyblue3", (void*)0x009acd}, {(void*)"deepskyblue4", (void*)0x00688b}, {(void*)"skyblue1", (void*)0x87ceff}, {(void*)"skyblue2", (void*)0x7ec0ee}, {(void*)"skyblue3", (void*)0x6ca6cd}, {(void*)"skyblue4", (void*)0x4a708b}, {(void*)"lightskyblue1", (void*)0xb0e2ff}, {(void*)"lightskyblue2", (void*)0xa4d3ee}, {(void*)"lightskyblue3", (void*)0x8db6cd}, {(void*)"lightskyblue4", (void*)0x607b8b}, {(void*)"slategray1", (void*)0xc6e2ff}, {(void*)"slategray2", (void*)0xb9d3ee}, {(void*)"slategray3", (void*)0x9fb6cd}, {(void*)"slategray4", (void*)0x6c7b8b}, {(void*)"lightsteelblue1", (void*)0xcae1ff}, {(void*)"lightsteelblue2", (void*)0xbcd2ee}, {(void*)"lightsteelblue3", (void*)0xa2b5cd}, {(void*)"lightsteelblue4", (void*)0x6e7b8b}, {(void*)"lightblue1", (void*)0xbfefff}, {(void*)"lightblue2", (void*)0xb2dfee}, {(void*)"lightblue3", (void*)0x9ac0cd}, {(void*)"lightblue4", (void*)0x68838b}, {(void*)"lightcyan1", (void*)0xe0ffff}, {(void*)"lightcyan2", (void*)0xd1eeee}, {(void*)"lightcyan3", (void*)0xb4cdcd}, {(void*)"lightcyan4", (void*)0x7a8b8b}, {(void*)"paleturquoise1", (void*)0xbbffff}, {(void*)"paleturquoise2", (void*)0xaeeeee}, {(void*)"paleturquoise3", (void*)0x96cdcd}, {(void*)"paleturquoise4", (void*)0x668b8b}, {(void*)"cadetblue1", (void*)0x98f5ff}, {(void*)"cadetblue2", (void*)0x8ee5ee}, {(void*)"cadetblue3", (void*)0x7ac5cd}, {(void*)"cadetblue4", (void*)0x53868b}, {(void*)"turquoise1", (void*)0x00f5ff}, {(void*)"turquoise2", (void*)0x00e5ee}, {(void*)"turquoise3", (void*)0x00c5cd}, {(void*)"turquoise4", (void*)0x00868b}, {(void*)"cyan1", (void*)0x00ffff}, {(void*)"cyan2", (void*)0x00eeee}, {(void*)"cyan3", (void*)0x00cdcd}, {(void*)"cyan4", (void*)0x008b8b}, {(void*)"darkslategray1", (void*)0x97ffff}, {(void*)"darkslategray2", (void*)0x8deeee}, {(void*)"darkslategray3", (void*)0x79cdcd}, {(void*)"darkslategray4", (void*)0x528b8b}, {(void*)"aquamarine1", (void*)0x7fffd4}, {(void*)"aquamarine2", (void*)0x76eec6}, {(void*)"aquamarine3", (void*)0x66cdaa}, {(void*)"aquamarine4", (void*)0x458b74}, {(void*)"darkseagreen1", (void*)0xc1ffc1}, {(void*)"darkseagreen2", (void*)0xb4eeb4}, {(void*)"darkseagreen3", (void*)0x9bcd9b}, {(void*)"darkseagreen4", (void*)0x698b69}, {(void*)"seagreen1", (void*)0x54ff9f}, {(void*)"seagreen2", (void*)0x4eee94}, {(void*)"seagreen3", (void*)0x43cd80}, {(void*)"seagreen4", (void*)0x2e8b57}, {(void*)"palegreen1", (void*)0x9aff9a}, {(void*)"palegreen2", (void*)0x90ee90}, {(void*)"palegreen3", (void*)0x7ccd7c}, {(void*)"palegreen4", (void*)0x548b54}, {(void*)"springgreen1", (void*)0x00ff7f}, {(void*)"springgreen2", (void*)0x00ee76}, {(void*)"springgreen3", (void*)0x00cd66}, {(void*)"springgreen4", (void*)0x008b45}, {(void*)"green1", (void*)0x00ff00}, {(void*)"green2", (void*)0x00ee00}, {(void*)"green3", (void*)0x00cd00}, {(void*)"green4", (void*)0x008b00}, {(void*)"chartreuse1", (void*)0x7fff00}, {(void*)"chartreuse2", (void*)0x76ee00}, {(void*)"chartreuse3", (void*)0x66cd00}, {(void*)"chartreuse4", (void*)0x458b00}, {(void*)"olivedrab1", (void*)0xc0ff3e}, {(void*)"olivedrab2", (void*)0xb3ee3a}, {(void*)"olivedrab3", (void*)0x9acd32}, {(void*)"olivedrab4", (void*)0x698b22}, {(void*)"darkolivegreen1", (void*)0xcaff70}, {(void*)"darkolivegreen2", (void*)0xbcee68}, {(void*)"darkolivegreen3", (void*)0xa2cd5a}, {(void*)"darkolivegreen4", (void*)0x6e8b3d}, {(void*)"khaki1", (void*)0xfff68f}, {(void*)"khaki2", (void*)0xeee685}, {(void*)"khaki3", (void*)0xcdc673}, {(void*)"khaki4", (void*)0x8b864e}, {(void*)"lightgoldenrod1", (void*)0xffec8b}, {(void*)"lightgoldenrod2", (void*)0xeedc82}, {(void*)"lightgoldenrod3", (void*)0xcdbe70}, {(void*)"lightgoldenrod4", (void*)0x8b814c}, {(void*)"lightyellow1", (void*)0xffffe0}, {(void*)"lightyellow2", (void*)0xeeeed1}, {(void*)"lightyellow3", (void*)0xcdcdb4}, {(void*)"lightyellow4", (void*)0x8b8b7a}, {(void*)"yellow1", (void*)0xffff00}, {(void*)"yellow2", (void*)0xeeee00}, {(void*)"yellow3", (void*)0xcdcd00}, {(void*)"yellow4", (void*)0x8b8b00}, {(void*)"gold1", (void*)0xffd700}, {(void*)"gold2", (void*)0xeec900}, {(void*)"gold3", (void*)0xcdad00}, {(void*)"gold4", (void*)0x8b7500}, {(void*)"goldenrod1", (void*)0xffc125}, {(void*)"goldenrod2", (void*)0xeeb422}, {(void*)"goldenrod3", (void*)0xcd9b1d}, {(void*)"goldenrod4", (void*)0x8b6914}, {(void*)"darkgoldenrod1", (void*)0xffb90f}, {(void*)"darkgoldenrod2", (void*)0xeead0e}, {(void*)"darkgoldenrod3", (void*)0xcd950c}, {(void*)"darkgoldenrod4", (void*)0x8b6508}, {(void*)"rosybrown1", (void*)0xffc1c1}, {(void*)"rosybrown2", (void*)0xeeb4b4}, {(void*)"rosybrown3", (void*)0xcd9b9b}, {(void*)"rosybrown4", (void*)0x8b6969}, {(void*)"indianred1", (void*)0xff6a6a}, {(void*)"indianred2", (void*)0xee6363}, {(void*)"indianred3", (void*)0xcd5555}, {(void*)"indianred4", (void*)0x8b3a3a}, {(void*)"sienna1", (void*)0xff8247}, {(void*)"sienna2", (void*)0xee7942}, {(void*)"sienna3", (void*)0xcd6839}, {(void*)"sienna4", (void*)0x8b4726}, {(void*)"burlywood1", (void*)0xffd39b}, {(void*)"burlywood2", (void*)0xeec591}, {(void*)"burlywood3", (void*)0xcdaa7d}, {(void*)"burlywood4", (void*)0x8b7355}, {(void*)"wheat1", (void*)0xffe7ba}, {(void*)"wheat2", (void*)0xeed8ae}, {(void*)"wheat3", (void*)0xcdba96}, {(void*)"wheat4", (void*)0x8b7e66}, {(void*)"tan1", (void*)0xffa54f}, {(void*)"tan2", (void*)0xee9a49}, {(void*)"tan3", (void*)0xcd853f}, {(void*)"tan4", (void*)0x8b5a2b}, {(void*)"chocolate1", (void*)0xff7f24}, {(void*)"chocolate2", (void*)0xee7621}, {(void*)"chocolate3", (void*)0xcd661d}, {(void*)"chocolate4", (void*)0x8b4513}, {(void*)"firebrick1", (void*)0xff3030}, {(void*)"firebrick2", (void*)0xee2c2c}, {(void*)"firebrick3", (void*)0xcd2626}, {(void*)"firebrick4", (void*)0x8b1a1a}, {(void*)"brown1", (void*)0xff4040}, {(void*)"brown2", (void*)0xee3b3b}, {(void*)"brown3", (void*)0xcd3333}, {(void*)"brown4", (void*)0x8b2323}, {(void*)"salmon1", (void*)0xff8c69}, {(void*)"salmon2", (void*)0xee8262}, {(void*)"salmon3", (void*)0xcd7054}, {(void*)"salmon4", (void*)0x8b4c39}, {(void*)"lightsalmon1", (void*)0xffa07a}, {(void*)"lightsalmon2", (void*)0xee9572}, {(void*)"lightsalmon3", (void*)0xcd8162}, {(void*)"lightsalmon4", (void*)0x8b5742}, {(void*)"orange1", (void*)0xffa500}, {(void*)"orange2", (void*)0xee9a00}, {(void*)"orange3", (void*)0xcd8500}, {(void*)"orange4", (void*)0x8b5a00}, {(void*)"darkorange1", (void*)0xff7f00}, {(void*)"darkorange2", (void*)0xee7600}, {(void*)"darkorange3", (void*)0xcd6600}, {(void*)"darkorange4", (void*)0x8b4500}, {(void*)"coral1", (void*)0xff7256}, {(void*)"coral2", (void*)0xee6a50}, {(void*)"coral3", (void*)0xcd5b45}, {(void*)"coral4", (void*)0x8b3e2f}, {(void*)"tomato1", (void*)0xff6347}, {(void*)"tomato2", (void*)0xee5c42}, {(void*)"tomato3", (void*)0xcd4f39}, {(void*)"tomato4", (void*)0x8b3626}, {(void*)"orangered1", (void*)0xff4500}, {(void*)"orangered2", (void*)0xee4000}, {(void*)"orangered3", (void*)0xcd3700}, {(void*)"orangered4", (void*)0x8b2500}, {(void*)"red1", (void*)0xff0000}, {(void*)"red2", (void*)0xee0000}, {(void*)"red3", (void*)0xcd0000}, {(void*)"red4", (void*)0x8b0000}, {(void*)"debianred", (void*)0xd70751}, {(void*)"deeppink1", (void*)0xff1493}, {(void*)"deeppink2", (void*)0xee1289}, {(void*)"deeppink3", (void*)0xcd1076}, {(void*)"deeppink4", (void*)0x8b0a50}, {(void*)"hotpink1", (void*)0xff6eb4}, {(void*)"hotpink2", (void*)0xee6aa7}, {(void*)"hotpink3", (void*)0xcd6090}, {(void*)"hotpink4", (void*)0x8b3a62}, {(void*)"pink1", (void*)0xffb5c5}, {(void*)"pink2", (void*)0xeea9b8}, {(void*)"pink3", (void*)0xcd919e}, {(void*)"pink4", (void*)0x8b636c}, {(void*)"lightpink1", (void*)0xffaeb9}, {(void*)"lightpink2", (void*)0xeea2ad}, {(void*)"lightpink3", (void*)0xcd8c95}, {(void*)"lightpink4", (void*)0x8b5f65}, {(void*)"palevioletred1", (void*)0xff82ab}, {(void*)"palevioletred2", (void*)0xee799f}, {(void*)"palevioletred3", (void*)0xcd6889}, {(void*)"palevioletred4", (void*)0x8b475d}, {(void*)"maroon1", (void*)0xff34b3}, {(void*)"maroon2", (void*)0xee30a7}, {(void*)"maroon3", (void*)0xcd2990}, {(void*)"maroon4", (void*)0x8b1c62}, {(void*)"violetred1", (void*)0xff3e96}, {(void*)"violetred2", (void*)0xee3a8c}, {(void*)"violetred3", (void*)0xcd3278}, {(void*)"violetred4", (void*)0x8b2252}, {(void*)"magenta1", (void*)0xff00ff}, {(void*)"magenta2", (void*)0xee00ee}, {(void*)"magenta3", (void*)0xcd00cd}, {(void*)"magenta4", (void*)0x8b008b}, {(void*)"orchid1", (void*)0xff83fa}, {(void*)"orchid2", (void*)0xee7ae9}, {(void*)"orchid3", (void*)0xcd69c9}, {(void*)"orchid4", (void*)0x8b4789}, {(void*)"plum1", (void*)0xffbbff}, {(void*)"plum2", (void*)0xeeaeee}, {(void*)"plum3", (void*)0xcd96cd}, {(void*)"plum4", (void*)0x8b668b}, {(void*)"mediumorchid1", (void*)0xe066ff}, {(void*)"mediumorchid2", (void*)0xd15fee}, {(void*)"mediumorchid3", (void*)0xb452cd}, {(void*)"mediumorchid4", (void*)0x7a378b}, {(void*)"darkorchid1", (void*)0xbf3eff}, {(void*)"darkorchid2", (void*)0xb23aee}, {(void*)"darkorchid3", (void*)0x9a32cd}, {(void*)"darkorchid4", (void*)0x68228b}, {(void*)"purple1", (void*)0x9b30ff}, {(void*)"purple2", (void*)0x912cee}, {(void*)"purple3", (void*)0x7d26cd}, {(void*)"purple4", (void*)0x551a8b}, {(void*)"mediumpurple1", (void*)0xab82ff}, {(void*)"mediumpurple2", (void*)0x9f79ee}, {(void*)"mediumpurple3", (void*)0x8968cd}, {(void*)"mediumpurple4", (void*)0x5d478b}, {(void*)"thistle1", (void*)0xffe1ff}, {(void*)"thistle2", (void*)0xeed2ee}, {(void*)"thistle3", (void*)0xcdb5cd}, {(void*)"thistle4", (void*)0x8b7b8b}, {(void*)"gray0", (void*)0x000000}, {(void*)"grey0", (void*)0x000000}, {(void*)"gray1", (void*)0x030303}, {(void*)"grey1", (void*)0x030303}, {(void*)"gray2", (void*)0x050505}, {(void*)"grey2", (void*)0x050505}, {(void*)"gray3", (void*)0x080808}, {(void*)"grey3", (void*)0x080808}, {(void*)"gray4", (void*)0x0a0a0a}, {(void*)"grey4", (void*)0x0a0a0a}, {(void*)"gray5", (void*)0x0d0d0d}, {(void*)"grey5", (void*)0x0d0d0d}, {(void*)"gray6", (void*)0x0f0f0f}, {(void*)"grey6", (void*)0x0f0f0f}, {(void*)"gray7", (void*)0x121212}, {(void*)"grey7", (void*)0x121212}, {(void*)"gray8", (void*)0x141414}, {(void*)"grey8", (void*)0x141414}, {(void*)"gray9", (void*)0x171717}, {(void*)"grey9", (void*)0x171717}, {(void*)"gray10", (void*)0x1a1a1a}, {(void*)"grey10", (void*)0x1a1a1a}, {(void*)"gray11", (void*)0x1c1c1c}, {(void*)"grey11", (void*)0x1c1c1c}, {(void*)"gray12", (void*)0x1f1f1f}, {(void*)"grey12", (void*)0x1f1f1f}, {(void*)"gray13", (void*)0x212121}, {(void*)"grey13", (void*)0x212121}, {(void*)"gray14", (void*)0x242424}, {(void*)"grey14", (void*)0x242424}, {(void*)"gray15", (void*)0x262626}, {(void*)"grey15", (void*)0x262626}, {(void*)"gray16", (void*)0x292929}, {(void*)"grey16", (void*)0x292929}, {(void*)"gray17", (void*)0x2b2b2b}, {(void*)"grey17", (void*)0x2b2b2b}, {(void*)"gray18", (void*)0x2e2e2e}, {(void*)"grey18", (void*)0x2e2e2e}, {(void*)"gray19", (void*)0x303030}, {(void*)"grey19", (void*)0x303030}, {(void*)"gray20", (void*)0x333333}, {(void*)"grey20", (void*)0x333333}, {(void*)"gray21", (void*)0x363636}, {(void*)"grey21", (void*)0x363636}, {(void*)"gray22", (void*)0x383838}, {(void*)"grey22", (void*)0x383838}, {(void*)"gray23", (void*)0x3b3b3b}, {(void*)"grey23", (void*)0x3b3b3b}, {(void*)"gray24", (void*)0x3d3d3d}, {(void*)"grey24", (void*)0x3d3d3d}, {(void*)"gray25", (void*)0x404040}, {(void*)"grey25", (void*)0x404040}, {(void*)"gray26", (void*)0x424242}, {(void*)"grey26", (void*)0x424242}, {(void*)"gray27", (void*)0x454545}, {(void*)"grey27", (void*)0x454545}, {(void*)"gray28", (void*)0x474747}, {(void*)"grey28", (void*)0x474747}, {(void*)"gray29", (void*)0x4a4a4a}, {(void*)"grey29", (void*)0x4a4a4a}, {(void*)"gray30", (void*)0x4d4d4d}, {(void*)"grey30", (void*)0x4d4d4d}, {(void*)"gray31", (void*)0x4f4f4f}, {(void*)"grey31", (void*)0x4f4f4f}, {(void*)"gray32", (void*)0x525252}, {(void*)"grey32", (void*)0x525252}, {(void*)"gray33", (void*)0x545454}, {(void*)"grey33", (void*)0x545454}, {(void*)"gray34", (void*)0x575757}, {(void*)"grey34", (void*)0x575757}, {(void*)"gray35", (void*)0x595959}, {(void*)"grey35", (void*)0x595959}, {(void*)"gray36", (void*)0x5c5c5c}, {(void*)"grey36", (void*)0x5c5c5c}, {(void*)"gray37", (void*)0x5e5e5e}, {(void*)"grey37", (void*)0x5e5e5e}, {(void*)"gray38", (void*)0x616161}, {(void*)"grey38", (void*)0x616161}, {(void*)"gray39", (void*)0x636363}, {(void*)"grey39", (void*)0x636363}, {(void*)"gray40", (void*)0x666666}, {(void*)"grey40", (void*)0x666666}, {(void*)"gray41", (void*)0x696969}, {(void*)"grey41", (void*)0x696969}, {(void*)"gray42", (void*)0x6b6b6b}, {(void*)"grey42", (void*)0x6b6b6b}, {(void*)"gray43", (void*)0x6e6e6e}, {(void*)"grey43", (void*)0x6e6e6e}, {(void*)"gray44", (void*)0x707070}, {(void*)"grey44", (void*)0x707070}, {(void*)"gray45", (void*)0x737373}, {(void*)"grey45", (void*)0x737373}, {(void*)"gray46", (void*)0x757575}, {(void*)"grey46", (void*)0x757575}, {(void*)"gray47", (void*)0x787878}, {(void*)"grey47", (void*)0x787878}, {(void*)"gray48", (void*)0x7a7a7a}, {(void*)"grey48", (void*)0x7a7a7a}, {(void*)"gray49", (void*)0x7d7d7d}, {(void*)"grey49", (void*)0x7d7d7d}, {(void*)"gray50", (void*)0x7f7f7f}, {(void*)"grey50", (void*)0x7f7f7f}, {(void*)"gray51", (void*)0x828282}, {(void*)"grey51", (void*)0x828282}, {(void*)"gray52", (void*)0x858585}, {(void*)"grey52", (void*)0x858585}, {(void*)"gray53", (void*)0x878787}, {(void*)"grey53", (void*)0x878787}, {(void*)"gray54", (void*)0x8a8a8a}, {(void*)"grey54", (void*)0x8a8a8a}, {(void*)"gray55", (void*)0x8c8c8c}, {(void*)"grey55", (void*)0x8c8c8c}, {(void*)"gray56", (void*)0x8f8f8f}, {(void*)"grey56", (void*)0x8f8f8f}, {(void*)"gray57", (void*)0x919191}, {(void*)"grey57", (void*)0x919191}, {(void*)"gray58", (void*)0x949494}, {(void*)"grey58", (void*)0x949494}, {(void*)"gray59", (void*)0x969696}, {(void*)"grey59", (void*)0x969696}, {(void*)"gray60", (void*)0x999999}, {(void*)"grey60", (void*)0x999999}, {(void*)"gray61", (void*)0x9c9c9c}, {(void*)"grey61", (void*)0x9c9c9c}, {(void*)"gray62", (void*)0x9e9e9e}, {(void*)"grey62", (void*)0x9e9e9e}, {(void*)"gray63", (void*)0xa1a1a1}, {(void*)"grey63", (void*)0xa1a1a1}, {(void*)"gray64", (void*)0xa3a3a3}, {(void*)"grey64", (void*)0xa3a3a3}, {(void*)"gray65", (void*)0xa6a6a6}, {(void*)"grey65", (void*)0xa6a6a6}, {(void*)"gray66", (void*)0xa8a8a8}, {(void*)"grey66", (void*)0xa8a8a8}, {(void*)"gray67", (void*)0xababab}, {(void*)"grey67", (void*)0xababab}, {(void*)"gray68", (void*)0xadadad}, {(void*)"grey68", (void*)0xadadad}, {(void*)"gray69", (void*)0xb0b0b0}, {(void*)"grey69", (void*)0xb0b0b0}, {(void*)"gray70", (void*)0xb3b3b3}, {(void*)"grey70", (void*)0xb3b3b3}, {(void*)"gray71", (void*)0xb5b5b5}, {(void*)"grey71", (void*)0xb5b5b5}, {(void*)"gray72", (void*)0xb8b8b8}, {(void*)"grey72", (void*)0xb8b8b8}, {(void*)"gray73", (void*)0xbababa}, {(void*)"grey73", (void*)0xbababa}, {(void*)"gray74", (void*)0xbdbdbd}, {(void*)"grey74", (void*)0xbdbdbd}, {(void*)"gray75", (void*)0xbfbfbf}, {(void*)"grey75", (void*)0xbfbfbf}, {(void*)"gray76", (void*)0xc2c2c2}, {(void*)"grey76", (void*)0xc2c2c2}, {(void*)"gray77", (void*)0xc4c4c4}, {(void*)"grey77", (void*)0xc4c4c4}, {(void*)"gray78", (void*)0xc7c7c7}, {(void*)"grey78", (void*)0xc7c7c7}, {(void*)"gray79", (void*)0xc9c9c9}, {(void*)"grey79", (void*)0xc9c9c9}, {(void*)"gray80", (void*)0xcccccc}, {(void*)"grey80", (void*)0xcccccc}, {(void*)"gray81", (void*)0xcfcfcf}, {(void*)"grey81", (void*)0xcfcfcf}, {(void*)"gray82", (void*)0xd1d1d1}, {(void*)"grey82", (void*)0xd1d1d1}, {(void*)"gray83", (void*)0xd4d4d4}, {(void*)"grey83", (void*)0xd4d4d4}, {(void*)"gray84", (void*)0xd6d6d6}, {(void*)"grey84", (void*)0xd6d6d6}, {(void*)"gray85", (void*)0xd9d9d9}, {(void*)"grey85", (void*)0xd9d9d9}, {(void*)"gray86", (void*)0xdbdbdb}, {(void*)"grey86", (void*)0xdbdbdb}, {(void*)"gray87", (void*)0xdedede}, {(void*)"grey87", (void*)0xdedede}, {(void*)"gray88", (void*)0xe0e0e0}, {(void*)"grey88", (void*)0xe0e0e0}, {(void*)"gray89", (void*)0xe3e3e3}, {(void*)"grey89", (void*)0xe3e3e3}, {(void*)"gray90", (void*)0xe5e5e5}, {(void*)"grey90", (void*)0xe5e5e5}, {(void*)"gray91", (void*)0xe8e8e8}, {(void*)"grey91", (void*)0xe8e8e8}, {(void*)"gray92", (void*)0xebebeb}, {(void*)"grey92", (void*)0xebebeb}, {(void*)"gray93", (void*)0xededed}, {(void*)"grey93", (void*)0xededed}, {(void*)"gray94", (void*)0xf0f0f0}, {(void*)"grey94", (void*)0xf0f0f0}, {(void*)"gray95", (void*)0xf2f2f2}, {(void*)"grey95", (void*)0xf2f2f2}, {(void*)"gray96", (void*)0xf5f5f5}, {(void*)"grey96", (void*)0xf5f5f5}, {(void*)"gray97", (void*)0xf7f7f7}, {(void*)"grey97", (void*)0xf7f7f7}, {(void*)"gray98", (void*)0xfafafa}, {(void*)"grey98", (void*)0xfafafa}, {(void*)"gray99", (void*)0xfcfcfc}, {(void*)"grey99", (void*)0xfcfcfc}, {(void*)"gray100", (void*)0xffffff}, {(void*)"grey100", (void*)0xffffff}, {(void*)"darkgrey", (void*)0xa9a9a9}, {(void*)"darkgray", (void*)0xa9a9a9}, {(void*)"darkblue", (void*)0x00008b}, {(void*)"darkcyan", (void*)0x008b8b}, {(void*)"darkmagenta", (void*)0x8b008b}, {(void*)"darkred", (void*)0x8b0000}, {(void*)"lightgreen", (void*)0x90ee90}, {NULL} /* sentinel */ }; 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(talker, "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.5.5/src/graph/plotfltk.c0000644000175000017500000001266212147140046015005 0ustar billbill/* $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. */ ///////////////////////////////////////////////////////////////////////////// // // 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; i= numcolors) col = numcolors-1; fl_color(color[col]); } static void DrawLines(void *data, long nb, struct plot_points *p) { long i; (void)data; for (i=1; 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; gen_rectdraw0(&pl, (void*)color, 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(1); 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(long f) /* This function initialises the structure rect.h: pari_plot */ { (void)f; 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.5.5/src/graph/rect.h0000644000175000017500000002160312147140046014103 0ustar billbill/* $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. */ 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 (*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 PLOT_POSTSCRIPT 0x80000 #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 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, void *data, long *w, long *x, long *y, long lw, double xs, double ys); /* architecture-dependent plot file (plotX.c ...) */ void PARI_get_plot(long fatal); void rectdraw0(long *w, long *x, long *y, long lw); ENDEXTERN pari-2.5.5/src/graph/plotX.c0000644000175000017500000001763412147140046014260 0ustar billbill/* $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. */ /*******************************************************************/ /* */ /* 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; }; static void SetForeground(void *data, long col) { struct data_x *dx = (struct data_x *) data; if (col >= dx->numcolors) { pari_warn(warner,"non-existent color: %ld", col); col = dx->numcolors-1; } 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); } 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; ierror_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; } void rectdraw0(long *w, long *x, long *y, long lw) { long oldwidth,oldheight; struct plot_eng plotX; struct data_x dx; double xs = 1, ys = 1; int screen, keystate; Display *display; GC gc; Window win; XEvent event; XSizeHints size_hints; XFontStruct *font_info; XSetWindowAttributes attrib; Atom wm_delete_window, wm_protocols; if (pari_daemon()) return; /* parent process returns */ pari_close(); PARI_get_plot(1); display = XOpenDisplay(NULL); font_info = XLoadQueryFont(display, "9x15"); if (!font_info) exiterr("cannot open 9x15 font"); XSetErrorHandler(Xerror); XSetIOErrorHandler(IOerror); PARI_ColorSetUp(display,pari_colormap); screen = DefaultScreen(display); win = XCreateSimpleWindow (display, RootWindow(display, screen), 0, 0, pari_plot.width, pari_plot.height, 4, PARI_Colors[1].pixel, PARI_Colors[0].pixel); size_hints.flags = PPosition | PSize; size_hints.x = 0; size_hints.y = 0; size_hints.width = pari_plot.width; size_hints.height = pari_plot.height; XSetStandardProperties (display, win, "rectplot", NULL, None, NULL, 0, &size_hints); wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False); wm_protocols = XInternAtom(display, "WM_PROTOCOLS", False); XSetWMProtocols(display,win,&wm_delete_window, 1); XSelectInput (display, win, ExposureMask | ButtonPressMask | KeyReleaseMask | StructureNotifyMask); /* enable backing-store */ attrib.backing_store = Always; attrib.backing_planes = AllPlanes; XChangeWindowAttributes(display,win,CWBackingStore|CWBackingPlanes,&attrib); gc = XCreateGC(display, win, 0, NULL); XSetFont(display, gc, font_info->fid); 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; 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, (void *)&dx, w, x, y,lw,xs,ys); } } } void PARI_get_plot(long fatal) { Display *display; int screen; if (pari_plot.init) return; if (!(display = XOpenDisplay(NULL))) { if (fatal) exiterr("no X server"); pari_err(talker, "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.5.5/src/graph/plotQt4.c0000644000175000017500000003643612147140046014522 0ustar billbill/* $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. */ ///////////////////////////////////////////////////////////////////////////// // // 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; if (col >= d->numcolors) col = d->numcolors-1; 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; double xs = double(this->width()) / pari_plot.width, ys = double(this->height()) / pari_plot.height; gen_rectdraw0(&plotQt, (void *)&d, 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(1); // 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(long f) /* This function initialises the structure rect.h: pari_plot */ { (void)f; 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.5.5/src/graph/plotQt.c0000644000175000017500000003765312147140046014440 0ustar billbill/* $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. */ ///////////////////////////////////////////////////////////////////////////// // // 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; if (col >= d->numcolors) col = d->numcolors-1; 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; double xs = double(this->width()) / pari_plot.width, ys = double(this->height()) / pari_plot.height; gen_rectdraw0(&plotQt, (void *)&d, 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(1); // 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(long f) /* This function initialises the structure rect.h: pari_plot */ { (void)f; 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.5.5/src/graph/plotnull.c0000644000175000017500000000145712147140046015017 0ustar billbill/* $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. */ #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(long f) { (void)f; pari_err(talker,"high resolution graphics disabled"); } pari-2.5.5/src/gp/0000755000175000017500000000000012212611624012276 5ustar billbillpari-2.5.5/src/gp/whatnow.c0000644000175000017500000000532612147140046014141 0ustar billbill/* $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. */ #include "pari.h" #include "paripriv.h" #include "gp.h" typedef struct whatnow_t { const char *name, *oldarg, *newarg; } whatnow_t; #define SAME NULL #define REMOV (char *)1L #define _REMOV {REMOV,NULL,NULL} #define _SAME {SAME,NULL,NULL} #include "whatnow.h" static void msg(PariOUT *out, const char *s) { out_term_color(out, c_HELP); out_print_text(out, s); out_putc(out, '\n'); out_term_color(out, c_NONE); } /* If flag = 0 (default): check if s existed in 1.39.15 and print verbosely * the answer. * Else: return 1 if function changed, 0 otherwise, and print help message * plus the above. */ int whatnow(PariOUT *out, const char *s, int flag) { int n; const char *def; whatnow_t wp; entree *ep; if (flag && s[0] && !s[1]) return 0; /* special case "i" and "o" */ n = 0; do def = (oldfonctions[n++]).name; while (def && strcmp(def,s)); if (!def) { int m = 0; do def = (functions_oldgp[m++]).name; while (def && strcmp(def,s)); n += m - 1; } /* Above linear search is slow, esp. if the symbol is not found. BUT no * point in wasting time by preallocating [ or autoloading ] a hashtable: * whatnow() is never used in a case where speed would be necessary */ if (!def) { if (!flag) msg(out, "As far as I can recall, this function never existed"); return 0; } wp = whatnowlist[n-1]; def = wp.name; if (def == SAME) { if (!flag) msg(out, "This function did not change"); return 0; } if (flag) { out_term_color(out, c_NONE); out_print_text(out, "\nA function with that name existed in GP-1.39.15; to run in backward compatibility mode, type \"default(compatible,3)\", or set \"compatible = 3\" in your GPRC file."); out_putc(out, '\n'); } if (def == REMOV) { msg(out, "This function was suppressed"); return 0; } if (!strcmp(def,"x*y")) ep = NULL; else { ep = is_entry(wp.name); if (!ep) pari_err(bugparier,"whatnow"); } out_puts(out, "New syntax: "); out_term_color(out, c_ERR); out_printf(out, "%s%s ===> %s%s\n\n", s, wp.oldarg, wp.name, wp.newarg); if (ep) msg(out, ep->help); out_term_color(out, c_NONE); return 1; } pari-2.5.5/src/gp/gp_rl.c0000644000175000017500000006700612147140046013560 0ustar billbill/* $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. */ /*******************************************************************/ /* */ /* 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 /***** Try to survive broken readline headers and obsolete versions *****/ #ifdef HAS_RL_MESSAGE # define USE_VARARGS # define PREFER_STDARG #endif #include #ifdef HAS_HISTORY_H # include #endif #ifndef HAS_HISTORY_H typedef struct HIST_ENTRY__ {char *line; void *data;} HIST_ENTRY; extern HIST_ENTRY *history_get(int); extern int history_length; #endif #ifdef HAS_RL_SAVE_PROMPT # define SAVE_PROMPT() rl_save_prompt() # define RESTORE_PROMPT() rl_restore_prompt() #else # ifdef HAS_UNDERSCORE_RL_SAVE_PROMPT extern void* _rl_restore_prompt(void), _rl_save_prompt(void); # define SAVE_PROMPT() _rl_save_prompt() # define RESTORE_PROMPT() _rl_restore_prompt() # else # define SAVE_PROMPT() # define RESTORE_PROMPT() # endif #endif #ifndef HAS_RL_MESSAGE extern int rl_message (const char*, ...); extern int rl_clear_message(), rl_begin_undo_group(), rl_end_undo_group(); extern int rl_read_key(), rl_stuff_char(); extern char *filename_completion_function(char *text,int state); extern char *username_completion_function(char *text,int state); #endif extern RLCI rl_last_func; ENDEXTERN #ifdef HAS_RL_COMPLETION_MATCHES # define COMPLETION_MATCHES(a,b) rl_completion_matches((a),(b)) # define FILE_COMPLETION rl_filename_completion_function # define USER_COMPLETION rl_username_completion_function # define DING rl_ding #else # define COMPLETION_MATCHES(a,b) \ (completion_matches((char*)(a),(CPFunction*)(b))) # define FILE_COMPLETION ((GF)filename_completion_function) # define USER_COMPLETION ((GF)username_completion_function) # define DING ding #endif /**************************************************************************/ 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; } SAVE_PROMPT(); rl_message("[%s: %s] ", msg, c? "on": "off"); c = rl_read_key(); 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: 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(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) #ifdef HAS_COMPLETION_APPEND_CHAR rl_completion_append_character = '\0'; /* Do not append space. */ #else pari_rl_back = 2; #endif } 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 = 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; SAVE_PROMPT(); rl_message("%s",""); /* rl_message("") ==> "zero length format" warning */ aide(s, flag); RESTORE_PROMPT(); rl_point = p; rl_end = e; pari_outfile = save; rl_clear_message(); #ifdef RL_REFRESH_LINE_OLDPROTO rl_refresh_line(); #else rl_refresh_line(0,0); #endif } /* 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; #if 0 /* OK, but rings a bell */ # ifdef HAS_RL_ATTEMPTED_COMPLETION_OVER rl_attempted_completion_over = 1; # endif return NULL; #else /* better: fake an empty completion, but don't append ' ' after it! */ # ifdef HAS_COMPLETION_APPEND_CHAR rl_completion_append_character = '\0'; # endif m = (char**)pari_malloc(2 * sizeof(char*)); m[0] = (char*)pari_malloc(1); *(m[0]) = 0; m[1] = NULL; return m; #endif } char ** pari_completion(char *text, int START, int END) { int i, first=0, start=START; #ifdef HAS_COMPLETION_APPEND_CHAR rl_completion_append_character = ' '; #endif 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)USER_COMPLETION; for(i=start+1;i<=END;i++) if (rl_line_buffer[i] == '/') { f = (GF)FILE_COMPLETION; 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, FILE_COMPLETION); 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, FILE_COMPLETION); 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) { #if 0 /* duplicate F1 */ rl_print_aide(buf,h_RL); # ifdef HAS_RL_ATTEMPTED_COMPLETION_OVER rl_attempted_completion_over = 1; # endif return NULL; #else 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; } } #endif } } 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 */ #ifndef HAS_RL_COMPLETION_FUNC_T # ifndef CPPFunction_defined # define CPPFunction Function # endif # define rl_completion_func_t CPPFunction #endif rl_attempted_completion_function = (rl_completion_func_t*) pari_completion; /* we always want the whole list of completions under emacs */ #ifdef HAS_RL_COMPLETION_QUERY_ITEMS if (GP_DATA->flags & gpd_EMACS) rl_completion_query_items = 0x8fff; #endif #ifdef HAS_RL_BIND_KEY_IN_MAP # ifdef _RL_FUNCTION_TYPEDEF # define Bind(a,b,c) (rl_bind_key_in_map((a),(b),(c))) # else # define Bind(a,b,c) (rl_bind_key_in_map((a), (Function*)(b), (c))) # endif #else # define Bind(a,b,c) #endif #ifdef _RL_FUNCTION_TYPEDEF # define Defun(a,b,c) (rl_add_defun((a), (b), (c))) #else # define Defun(a,b,c) (rl_add_defun((char*)(a), (Function*)(b), (c))) #endif Defun("short-help", rl_short_help, -1); Defun("long-help", rl_long_help, -1); Defun("pari-complete", pari_rl_complete, '\t'); Defun("pari-matched-insert", pari_rl_default_matched_insert, -1); Defun("pari-matched-insert-suspend", pari_rl_matched_insert_suspend, -1); Defun("pari-matched-insert-restore", pari_rl_matched_insert_restore, -1); Defun("pari-forward-sexp", pari_rl_forward_sexp, -1); Defun("pari-backward-sexp", pari_rl_backward_sexp, -1); Bind('h', rl_short_help, emacs_meta_keymap); Bind('H', rl_long_help, emacs_meta_keymap); # ifdef HAS_RL_GENERIC_BIND #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 */ # endif Bind('(', pari_rl_matched_insert, emacs_standard_keymap); Bind('[', pari_rl_matched_insert, emacs_standard_keymap); Bind(6, pari_rl_forward_sexp, emacs_meta_keymap); /* M-C-f */ Bind(2, pari_rl_backward_sexp, emacs_meta_keymap); /* M-C-b */ #ifdef EMACS_DOS_KEYMAP Bind(';', rl_short_help, emacs_dos_keymap); /* F1 */ Bind('T', rl_long_help, emacs_dos_keymap); /* Shift-F1 */ Bind(155, pari_rl_backward_sexp, emacs_dos_keymap); /* Alt-Left */ Bind(157, pari_rl_forward_sexp, emacs_dos_keymap); /* Alt-Right*/ #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.5.5/src/gp/highlvl.h0000644000175000017500000001752512201011602014102 0ustar billbill/* This file is autogenerated from the database. */ /* See src/desc/gen_proto */ /* Do not edit*/ entree functions_highlevel[]={ {"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 argument code 'code'. If 'lib' is omitted use 'libpari.so'. If 'gpname' is omitted, use 'name'."}, {"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 minima (resp. the maxima) 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 points 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 void install0(char *name, char *code, char *gpname, char *lib) { void *f, *handle; if (! *lib) lib = DL_DFLT_NAME; if (! *gpname) gpname = name; if (lib) lib = path_expand(lib); #ifndef RTLD_GLOBAL /* OSF1 has dlopen but not RTLD_GLOBAL*/ # define RTLD_GLOBAL 0 #endif handle = dlopen(lib, RTLD_LAZY|RTLD_GLOBAL); if (!handle) { const char *s = dlerror(); if (s) err_printf("%s\n\n",s); if (lib) pari_err(talker,"couldn't open dynamic library '%s'",lib); pari_err(talker,"couldn't open dynamic symbol table of process"); } f = dlsym(handle, name); if (!f) { if (lib) pari_err(talker,"can't find symbol '%s' in library '%s'",name,lib); pari_err(talker,"can't find symbol '%s' in dynamic symbol table of process",name); } if (lib) pari_free(lib); (void)install(f, gpname, code); } #else # ifdef _WIN32 # include void install0(char *name, char *code, char *gpname, char *lib) { FARPROC f; 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 #ifdef DL_DFLT_NAME if (! *lib) lib = DL_DFLT_NAME; #endif if (! *gpname) gpname=name; if (lib) lib = path_expand(lib); handle = LoadLibrary(lib); if (!handle) { if (lib) pari_err(talker,"couldn't open dynamic library '%s'",lib); pari_err(talker,"couldn't open dynamic symbol table of process"); } f = GetProcAddress(handle,name); if (!f) { if (lib) pari_err(talker,"can't find symbol '%s' in library '%s'",name,lib); pari_err(talker,"can't find symbol '%s' in dynamic symbol table of process",name); } if (lib) pari_free(lib); install((void*)f,gpname,code); } # else void install0(char *name, char *code, char *gpname, char *lib) { pari_err(archer); } #endif #endif void gpinstall(char *s, char *code, char *gpname, char *lib) { if (GP_DATA->secure) { char *msg = pari_sprintf("[secure mode]: about to install '%s'", s); pari_ask_confirm(msg); pari_free(msg); } install0(s, code, gpname, lib); } #include "highlvl.h" pari-2.5.5/src/gp/gp_default.h0000644000175000017500000000133412201011602014546 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,"",""}, {"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.5.5/src/gp/gp.c0000644000175000017500000020040012147140046013046 0ustar billbill/* $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. */ /*******************************************************************/ /** **/ /** PARI CALCULATOR **/ /** **/ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #include "gp.h" #ifdef _WIN32 # include # ifndef WINCE # include # endif #endif #ifdef READLINE BEGINEXTERN # include ENDEXTERN #endif /********************************************************************/ /** **/ /** STRINGS **/ /** **/ /********************************************************************/ #define skip_space(s) while (isspace((int)*s)) s++ #define skip_alpha(s) while (isalpha((int)*s)) s++ static char * translate(char **src, char *s) { 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(talker,"unfinished string"); } t++; s++; } if (*t == '"') { if (t[1] != '"') break; t += 2; continue; } *s++ = *t++; } *s=0; *src=t; return s; } #define match2(s,c) if (*s != c) \ pari_err(talker,"expected character: '%c' instead of",c); /* 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) { match2(src, '"'); src++; s = translate(&src, s); match2(src, '"'); 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(talker, "missing DATA_[BEGIN | END] in TeXmacs command"); s++; if (strncmp(s, "special:", 8)) pari_err(talker, "unrecognized TeXmacs command"); s += 8; if (*s != '(' || *send-- != ')') pari_err(talker, "missing enclosing parentheses for TeXmacs command"); s++; t = s; skip_alpha(s); c->cmd = pari_strndup(t, s - t); 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); else { /* read integer */ t = s; while (isdigit((int)*s)) s++; strncpy(u, t, s - t); u[s-t] = 0; } 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(talker,"Texmacs_stdin command %s not implemented", c.cmd); if (c.n != 2) pari_err(talker,"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(talker, "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; static char *Help; static char * init_help(void) { char *h = os_getenv("GPHELP"); # ifdef GPHELP if (!h) h = (char*)GPHELP; # 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; disable_exception_handler = 1; pari_puts("---- (type RETURN to continue) ----"); /* 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'); disable_exception_handler = 0; } 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; 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(ep->value) == t_CLOSURE) break; /* fall through */ case EpNEW: continue; } m = ep->menu; if ((n < 0 && m && m < 13) || m == n) stack_pushp(&s_L, (void*)ep->name); } stack_pushp(&s_L, NULL); print_fun_list(t_L, term_height()-4); 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, \ with a Subject: field containing the word \"subscribe\". \ An archive is kept at the WWW site mentioned above. You can also reach the \ authors directly by email: 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\ \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} : change 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 {n} : print stack information\n\ \\t : print the list of PARI types\n\ \\u : print the list of user-defined 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, bnf, bnr\n\ diff, codiff: different and codifferent nf, bnf, bnr\n\ disc : discriminant ell, nf, bnf, bnr\n\ e, f : inertia/residue degree prid\n\ fu : fundamental units bnf, bnr\n\ gen : generators bid, prid, clgp, bnf, bnr\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\n\ nf : number field nf, bnf, bnr\n\ no : number of elements bid, clgp, bnf, bnr\n\ omega, eta: [w1,w2] and [eta1, eta2] ell\n\ p : rational prime below prid prid\n\ pol : defining polynomial nf, bnf, bnr\n\ reg : regulator bnf, bnr\n\ roots: roots ell, nf, bnf, bnr\n\ sign,r1,r2 : signature nf, bnf, bnr\n\ t2 : t2 matrix nf, bnf, bnr\n\ tate : Tate's [u^2, u, q] ell\n\ tu : torsion unit and its order bnf, bnr\n\ w : Mestre's w ell\n\ zk : integral basis nf, bnf, bnr\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], ar[32], *str; const char *opt = ""; char *t; pariFILE *z; FILE *f; if (!has_ext_help()) pari_err(talker,"no external help program"); t = filter_quotes(s); str = (char*)pari_malloc(strlen(Help) + strlen(t) + 64); *ar = 0; if (num < 0) opt = "-k"; else if (t[strlen(t)-1] != '@') sprintf(ar,"@%d",num); sprintf(str,"%s -fromgp %s %c%s%s%c",Help,opt, SHELL_Q,t,ar,SHELL_Q); z = try_pipe(str,0); f = z->file; pari_free(str); 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", 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. */ else if (!is_keyword_char(c) && c != '@') { s[-1] = 0; return; } } } /* don't mess readline display */ static void aide_print(const char *s1, const char *s2) { pari_printf("%s: %s\n", s1, s2); } static void aide0(const char *s0, int flag) { long n, long_help = flag & h_LONG; entree *ep,*ep1; char *s; s = get_sep(s0); if (isdigit((int)*s)) { n = atoi(s); if (n < 0 || n > 15) pari_err(syntaxer,"no such section in help: ?",s,s); if (n == 12) community(); else if (long_help) external_help(s,3); else commands(n); 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)) cut_trailing_garbage(s); if (flag & h_APROPOS) { external_help(s,-1); return; } 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 && long_help) { if (!strcmp(ep->name, "default")) { char *t = s+7, *e; skip_space(t); if (*t == '(') { t++; skip_space(t); e = t; skip_alpha(e); *e = '\0'; /* safe: get_sep() made it a copy */ if (pari_is_default(t)) { external_help(t, 2); return; } } } } if (!ep) { if (long_help) external_help(s,3); else { if (pari_is_default(s)) aide_print(s,"default"); else if (!cb_pari_whatnow(pariOut, s,1)) aide_print(s,"unknown identifier"); } return; } ep1 = ep; ep = do_alias(ep); s0 = s; if (ep1 != ep) { pari_printf("%s is aliased to:\n\n",s0); s0 = ep->name; } switch(EpVALENCE(ep)) { case EpVAR: if (typ(ep->value)==t_CLOSURE && typ(gel(ep->value,6))==t_VEC) { GEN str=gel(ep->value,6); if (!ep->help || long_help) pari_printf("%s(%s)=%s",ep->name,GSTR(gel(str,1)),GSTR(gel(str,2))); if (!ep->help) return; if (long_help) { pari_puts("\n\n"); long_help=0; } } else if (!ep->help) { aide_print(s, "user defined variable"); return; } long_help=0; break; case EpINSTALL: if (!ep->help) { aide_print(s, "installed function"); return; } long_help=0; break; case EpNEW: if (!ep->help) { aide_print(s, "new identifier (no valence assigned)"); return; }; long_help=0; break; } if (long_help) { external_help(ep->name,3); return; } if (ep->help) { print_text(ep->help); return; } pari_err(bugparier,"aide (no help found)"); } void aide(const char *s, long flag) { 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'); } /********************************************************************/ /** **/ /** GP HEADER **/ /** **/ /********************************************************************/ static char * what_readline(void) { char *s; #ifdef READLINE const char *ver; char *extra = stackmalloc(strlen(READLINE) + 32); # if defined(HAS_RL_LIBRARY_VERSION) || defined(FAKE_RL_LIBRARY_VERSION) # ifdef FAKE_RL_LIBRARY_VERSION extern char *rl_library_version; # endif if (strcmp(READLINE, rl_library_version)) { ver = (char*)rl_library_version; (void)sprintf(extra, " [was v%s in Configure]", READLINE); } else # endif { ver = READLINE; extra[0] = 0; } s = stackmalloc(3 + strlen(ver) + 8 + strlen(extra)); (void)sprintf(s, "v%s %s%s", ver, (GP_DATA->use_readline)? "enabled": "disabled", extra); #else s = (char*)"not compiled in"; #endif return s; } 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 "g++-%s" # else # define Format "gcc-%s" # endif s = stackmalloc(4 + strlen(GCC_VERSION) + 1); (void)sprintf(s, Format, GCC_VERSION); #else # ifdef _MSC_VER s = stackmalloc(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(); center(paricfg_version); center(paricfg_buildinfo); buf = stackmalloc(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); ver = what_readline(); buf = stackmalloc(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-2013 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, maxprime()); } /********************************************************************/ /** **/ /** METACOMMANDS **/ /** **/ /********************************************************************/ #define pariputs_opt(s) if (!(GP_DATA->flags & gpd_QUIET)) pari_puts(s) void gp_quit(long exitcode) { if (Help) free((void*)Help); free_graph(); pari_close(); kill_buffers_upto(NULL); term_color(c_NONE); 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(openfiler,"input",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(syntaxer,"unexpected character", tch,tch-1); } } /* 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); s+=strlen(s); 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); term_get_color(s, c_NONE); s+=strlen(s); *s++ = '.'; *s++ = '\n'; *s = 0; return buf; } static int chron(char *s) { if (*s) { /* if "#" or "##" timer metacommand. Otherwise let the parser get it */ if (*s == '#') s++; if (*s) return 0; pari_puts( " *** last result computed in " ); pari_puts( gp_format_time(GP_DATA->last_time) ); } 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); #define err_gprc(s,t,u) { err_printf("\n"); pari_err(syntaxer,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, path [ to gp binary ] */ static FILE * gprc_get(char *path) { 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]; str = strcpy((char*)pari_malloc(l+7), home); if (free_it) pari_free((void*)home); s = str + l; if (c != '/' && c != '\\') *s++ = '/'; #ifdef UNIX *s = '.'; /* .gprc */ #else *s = '_'; /* _gprc */ #endif strcpy(s+1, "gprc"); f = gprc_chk(str); /* in $HOME */ if (!f) f = gprc_chk(s); /* in . */ if (!f) f = gprc_chk("/etc/gprc"); if (!f) f = gprc_chk("C:/_gprc"); if (!f) { /* in 'gp' directory */ char *t = path + strlen(path); while (t > path && *t != '/') t--; if (*t == '/') { long l = t - path + 1; t = (char*)pari_malloc(l + 6); strncpy(t, path, l); strcpy(t+l, s); f = gprc_chk(t); pari_free(t); } } 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 writeable) * 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); stack_pushp(&s_bufstack, (void*)b); return b; } static jmp_buf *env; static pari_stack s_env; static void gp_initrc(pari_stack *p_A, char *path) { char *nexts,*s,*t; FILE *file = gprc_get(path); Buffer *b; filtre_t F; VOLATILE long c = 0; if (!file) return; b = filtered_buffer(&F); (void)stack_new(&s_env); for(;;) { 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); else strcpy(t,s); stack_pushp(p_A,t); } else { /* set default */ t = s; while (*t && *t != '=') t++; if (*t != '=') err_gprc("missing '='",t,b->buf); *t++ = 0; if (*t == '"') (void)readstring(t, 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]; /* 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 RL_PROMPT_START_IGNORE if (GP_DATA->use_readline) *s++ = RL_PROMPT_START_IGNORE; #endif term_get_color(s, c); #ifdef RL_PROMPT_START_IGNORE if (GP_DATA->use_readline) { s+=strlen(s); *s++ = RL_PROMPT_END_IGNORE; *s = 0; } #endif } 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); } 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 void update_logfile(const char *prompt, const char *s) { if (!pari_logfile) return; switch (logstyle) { case logstyle_TeX: fprintf(pari_logfile, "\\PARIpromptSTART|%s\\PARIpromptEND|%s\\PARIinputEND|%%\n", prompt,s); break; case logstyle_plain: fprintf(pari_logfile,"%s%s\n",prompt,s); break; case logstyle_color: { pari_sp av = avma; fprintf(pari_logfile,"%s%s%s%s%s\n",term_get_color(NULL,c_PROMPT), prompt, term_get_color(NULL,c_INPUT), s, term_get_color(NULL,c_NONE)); avma = av; break; } } } void echo_and_log(const char *prompt, const char *s) { if (GP_DATA->echo) { pari_puts(prompt); pari_puts(s); pari_putc('\n'); } else 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; } static int is_interactive(void) { ulong f = GP_DATA->flags&(gpd_TEXMACS|gpd_TEST); return pari_infile == stdin && !f && gp_is_interactive; } /* 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; disable_exception_handler = 1; 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) { #ifdef READLINE if (GP_DATA->use_readline) { res = get_line_from_readline(p, Prompt_cont, F); goto END; } #endif pari_puts(p); pari_flush(); } res = get_line_from_file(p, F, pari_infile); #ifdef READLINE END: #endif if (!disable_color) { term_color(c_NONE); pari_flush(); } disable_exception_handler = 0; return res; } /* kill all history entries since loc */ static void prune_history(gp_hist *H, long loc) { long i, j; i = (H->total-1) % H->size; j = H->total - loc; for ( ; j > 0; i--,j--) { if (H->res[i]) { gunclone(H->res[i]); H->res[i] = NULL; } if (!i) i = H->size; } H->total = loc; } static int is_silent(char *s) { return s[strlen(s) - 1] == ';'; } 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 pari_sp av = avma; filtre_t F; Buffer *b = filtered_buffer(&F); struct gp_context rec; for(;;) { if (dorecover) { /* set a recovery point */ static long tloc, outtyp; long er; outtyp = GP_DATA->fmt->prettyp; tloc = pari_nb_hist(); gp_context_save(&rec); /* recover: jump from error [ > 0 ] or allocatemem [ -1 ] */ if ((er = setjmp(env[s_env.n-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; } GP_DATA->fmt->prettyp = outtyp; prune_history(GP_DATA->hist, tloc); } else { /* allocatemem */ filestate_restore(rec.file); gp_context_save(&rec); } avma = av = top; kill_buffers_upto(b); } } 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) { #if defined(_WIN32) || defined(__CYGWIN32__) win32ctrlc = 0; #endif 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'); GP_DATA->last_time = timer_delay(GP_DATA->T); if (GP_DATA->chrono) { pari_puts( "time = " ); pari_puts( gp_format_time(GP_DATA->last_time) ); } if (z == gnil) continue; if (GP_DATA->simplify) z = simplify_shallow(z); z = pari_add_hist(z); if (! is_silent(b->buf) ) gp_output(z, GP_DATA); } } /********************************************************************/ /* */ /* EXCEPTION HANDLER */ /* */ /********************************************************************/ static void gp_sigint_fun(void) { if (GP_DATA->flags & gpd_TEXMACS) tm_start_output(); pari_sigint( gp_format_time(timer_get(GP_DATA->T)) ); } #ifdef SIGALRM static void gp_alarm_fun(void) { if (GP_DATA->flags & gpd_TEXMACS) tm_start_output(); pari_err(alarmer, gp_format_time(timer_get(GP_DATA->T))); } #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; 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; char promptbuf[MAX_PROMPT_LEN + 24]; long nenv, oldframe_level = frame_level; pari_sp av; if (numerr == syntaxer) return 0; if (numerr == errpile) { evalstate_clone(); avma = top; } b = filtered_buffer(&F); nenv=stack_new(&s_env); gp_context_save(&rec); frame_level = closure_context(oldframe_level); pari_infile = newfile(stdin, "stdin", mf_IN)->file; term_color(c_ERR); pari_putc('\n'); if (sigint) print_errcontext(pariOut, "Break loop: type to continue; 'break' to go back to GP", NULL, NULL); else print_errcontext(pariOut, "Break loop: type 'break' to go back to GP", 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; longjmp(env[s_env.n-1], er); } gp_context_restore(&rec); closure_err(); frame_level = closure_context(oldframe_level); pari_infile = newfile(stdin, "stdin", mf_IN)->file; } term_color(c_NONE); if (gp_read_line(&F, prompt)) { /* Empty input --> continue computation if break loop initiated * by ^C (will continue) */ if (! *(b->buf) && sigint) break; #if defined(_WIN32) || defined(__CYGWIN32__) win32ctrlc = 0; #endif if (check_meta(b->buf, 0)) continue; x = closure_evalbrk(pari_compile_str(b->buf,0), &br_status); if (br_status) goto GP_EOF; if (x == gnil || is_silent(b->buf)) continue; term_color(c_OUTPUT); gen_output(x, GP_DATA->fmt); pari_putc('\n'); continue; } /* EOF or break/next/return */ GP_EOF: if (pari_infile != stdin) { /* were reading a file from the break loop, and are done : close it */ if (popinfile()) { go_on = 0; break; /* should not happen */ } } else { /* user typed in break loop : exit the debuger */ go_on = 0; break; } } s_env.n=nenv; frame_level = oldframe_level; gp_context_restore(&rec); pop_buffer(); return go_on; } /* numerr < 0: from SIGINT */ static void gp_err_recover(long numerr) { longjmp(env[s_env.n-1], numerr); } /* 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; if (s_env.n>=1) { err_printf("\n"); err_flush(); gp_err_recover(numerr>=0? numerr: talker); } 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(talker, "[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; } GEN externstr(const char *s) { pari_sp av = avma; long i, nz = 16; GEN z = cgetg(nz + 1, t_VEC); pariFILE *F; Buffer *b; input_method IM; check_secure(s); F = try_pipe(s, mf_IN); b = new_buffer(); IM.fgets = &fgets; IM.file = F->file; 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); pari_fclose(F); setlg(z, i); return gerepilecopy(av, 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(talker, "system(\"%s\") failed", s); #else pari_err(archer); #endif } void alarm0(long s) { if (s < 0) pari_err(talker,"delay must be non-negative"); #ifdef HAS_ALARM alarm(s); #else if (s) pari_err(archer,"alarm"); #endif } /*******************************************************************/ /** **/ /** 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; } static void read_opt(pari_stack *p_A, long argc, char **argv) { 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_outfile = stderr; while (i < argc) { char *t = argv[i]; if (*t++ != '-') break; i++; switch(*t++) { case 'b': b = read_arg(&i,t,argc,argv); pari_warn(warner, "buffersize is no longer used. -b ignored"); break; case 'p': p = read_arg(&i,t,argc,argv); break; case 's': s = read_arg(&i,t,argc,argv); break; case 'e': if (strncmp(t,"macs",4)) usage(argv[0]); /* obsolete */ f |= gpd_EMACS; break; case 'q': f |= gpd_QUIET; break; case 't': if (strncmp(t,"est",3)) usage(argv[0]); /* obsolete */ f |= gpd_TEST; break; case 'f': initrc = 0; 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, "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; init80col(); } else if (initrc) gp_initrc(p_A, argv[0]); for ( ; i < argc; i++) 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); if (GP_DATA->flags & (gpd_EMACS|gpd_TEXMACS|gpd_TEST)) disable_color = 1; pari_outfile = stdout; } #ifdef WINCE int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) { char **argv = NULL; int argc = 1; #else int main(int argc, char **argv) { #endif void **A; pari_stack s_A; GP_DATA = default_gp_data(); stack_init(&s_env, sizeof(*env), (void**)&env); (void)stack_new(&s_env); if (setjmp(env[s_env.n-1])) { puts("### Errors on startup, exiting...\n\n"); exit(1); } gp_is_interactive = pari_stdin_isatty(); pari_init_defaults(); stack_init(&s_A,sizeof(*A),(void**)&A); stack_init(&s_bufstack, sizeof(Buffer*), (void**)&bufstack); cb_pari_err_recover = gp_err_recover; pari_init_opts(1000000 * sizeof(long), 500000, INIT_SIGm); 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); #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; } 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(void) { const char *s = " \n"; long i = 2000; pari_puts("\n\n"); pari_flush(); /* start translation */ while (--i) pari_puts(s); pari_puts("\n"); pari_flush(); } /* 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; 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 *o_out, *o_logfile = pari_logfile; if (!prettyp_init()) return 0; o_out = pari_outfile; /* save state */ /* Emit first: there may be lines before the prompt */ if (n) term_color(c_OUTPUT); pari_flush(); pari_outfile = GP_DATA->pp->file->file; T.prettyp = f_TEX; pari_logfile = NULL; /* 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)) { char s[128]; if (*c_hist || *c_out) sprintf(s, "\\LITERALnoLENGTH{%s}\\%%%ld =\\LITERALnoLENGTH{%s} ", c_hist, n, c_out); else sprintf(s, "\\%%%ld = ", n); pari_puts(s); } if (o_logfile) { switch (logstyle) { case logstyle_plain: fprintf(o_logfile, "%%%ld = ", n); break; case logstyle_color: fprintf(o_logfile, "%s%%%ld = %s", c_hist, n, c_out); break; case logstyle_TeX: fprintf(o_logfile, "\\PARIout{%ld}", n); break; } } avma = av; } /* output */ gen_output(z, &T); /* flush and restore, output to logfile */ prettyp_wait(); if (o_logfile) { pari_outfile = o_logfile; if (logstyle == logstyle_TeX) { T.TeXstyle |= TEXSTYLE_BREAK; gen_output(z, &T); pari_putc('%'); } else { T.prettyp = f_RAW; gen_output(z, &T); } pari_putc('\n'); pari_flush(); } pari_logfile = o_logfile; pari_outfile = o_out; 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); free(s); term_color(c_NONE); pari_putc('\n'); } void gp_output(GEN z, gp_data *G) { if (G->flags & gpd_TEST) { init80col(); 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(syntaxer, "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(syntaxer, "incorrect value for graphcolormap", p, t); } else if (*p == '"') { s += sizeof(long)+1; while (*p && *++p != '"') s++; if (!*p) pari_err(syntaxer, "incorrect value for graphcolormap", p, t); s = (s+sizeof(long)-1) & ~(sizeof(long)-1); } else if (*p == ',') l++; if (l < 4) pari_err(talker, "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(syntaxer, 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(syntaxer, "incorrect value for graphcolormap", p, t); } 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(syntaxer, "incorrect value for graphcolors", p, t); if (*++p) pari_err(syntaxer, "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; } 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(talker,"[secure mode]: can't modify 'help' default (to %s)",v); if (Help) pari_free((void*)Help); Help = path_expand(v); } 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); } pari-2.5.5/src/gp/gp.h0000644000175000017500000000535612147140046013070 0ustar billbill/* $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. */ /*************************************************************************/ /* */ /* GP-SPECIFIC DECLARATIONS */ /* */ /*************************************************************************/ BEGINEXTERN void aide(const char *s, long flag); void echo_and_log(const char *prompt, const char *s); int get_line_from_readline(const char *prompt, const char *prompt_cont, filtre_t *F); void gp_output(GEN z, gp_data *G); void init_readline(void); void texmacs_completion(const char *s, long pos); void print_fun_list(char **list, long nbli); /* aide() */ #define h_REGULAR 0 #define h_LONG 1 #define h_APROPOS 2 #define h_RL 4 /* readline completions */ extern const char *keyword_list[]; /* TeXmacs */ #define DATA_BEGIN ((char) 2) #define DATA_END ((char) 5) #define DATA_ESCAPE ((char) 27) /* gp specific routines */ void alarm0(long s); GEN extern0(const char *cmd); GEN externstr(const char *cmd); void gp_quit(long exitcode); GEN input0(void); GEN read0(const char *s); void system0(const char *cmd); int whatnow(PariOUT *out, const char *s, int silent); GEN sd_breakloop(const char *v, long flag); GEN sd_echo(const char *v, long flag); GEN sd_graphcolormap(const char *v, long flag); GEN sd_graphcolors(const char *v, long flag); GEN sd_help(const char *v, long flag); GEN sd_histfile(const char *v, long flag); GEN sd_lines(const char *v, long flag); GEN sd_prompt(const char *v, long flag); GEN sd_prompt_cont(const char *v, long flag); GEN sd_psfile(const char *v, long flag); GEN sd_readline(const char *v, long flag); GEN sd_recover(const char *v, long flag); GEN sd_timer(const char *v, long flag); #define MAX_PROMPT_LEN 128 const char *do_prompt(char *buf, const char *prompt, filtre_t *F); extern entree functions_highlevel[]; /* list of GP-specific defaults */ extern entree functions_gp_default[], functions_gp_rl_default[]; /* list of GP-specific functions */ extern entree functions_gp[]; /* list of old GP-specific fonctions (up to 1.39.15) */ extern entree functions_oldgp[]; ENDEXTERN pari-2.5.5/src/gp/gp_init.c0000644000175000017500000001730012147140046014076 0ustar billbill/* $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. */ /*******************************************************************/ /* */ /* 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(typeer,"allocatemem"); newsize = itou(z); if (signe(z) < 0) pari_err(talker,"negative size in allocatemem"); } 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.5.5/src/gp/whatnow.h0000644000175000017500000003273312147140105014144 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, {"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)"}, {"ellpow","(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)"}, {"polroots","(x)","(x,1)"}, _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.5.5/src/gp/gp_init.h0000644000175000017500000000261112201011602014064 0ustar billbill/* This file is autogenerated from the database. */ /* See src/desc/gen_proto */ /* Do not edit*/ entree functions_gp[]={ {"alarm",0,(void*)alarm0,11,"vD0,L,","alarm({s = 0}): trigger an \"alarmer\" exception after s seconds, cancelling any previously set alarm. Stop a pending alarm if s = 0 or is omitted."}, {"allocatemem",0,(void*)allocatemem0,11,"vDG","allocatemem({s=0}): allocates a new stack of s bytes. doubles the stack if s is omitted."}, {"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."}, {"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.5.5/src/modules/0000755000175000017500000000000012212611624013340 5ustar billbillpari-2.5.5/src/modules/stark.c0000644000175000017500000027522112147140047014644 0ustar billbill/* $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. */ /*******************************************************************/ /* */ /* 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(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 = const_vecsmall(G.r, 0); 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); /* > 1 */ 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); 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 (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))) prdiff[nd++] = 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) 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 DA, DB be resp. the matrix of the relations of A and B, compute the kernel of s. If DA = 0 then A is free */ static GEN ComputeKernel0(GEN P, GEN DA, GEN DB) { pari_sp av = avma; long nbA = lg(DA)-1, rk; GEN U; rk = nbA + lg(DB) - lg(ZM_hnfall(shallowconcat(P, DB), &U, 1)); U = vecslice(U, 1,rk); U = rowslice(U, 1,nbA); if (!gequal0(DA)) U = shallowconcat(U, DA); return gerepileupto(av, ZM_hnf(U)); } /* 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 Mrm, Mrq, P; Mrm = diagonal_shallow(bnr_get_cyc(bnrm)); Mrq = diagonal_shallow(gel(dtQ,2)); P = ZM_mul(gel(dtQ,3), bnrsurjection(bnrm, bnrn)); return gerepileupto(av, ComputeKernel0(P, Mrm, Mrq)); } 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 pr be a prime (pr may divide mod(bnr)), compute the indexes e,f of the splitting of pr in the class field nf(bnr/subgroup) */ static GEN GetIndex(GEN pr, GEN bnr, GEN subgroup) { long v, e, f; pari_sp av = avma; GEN bnf, mod, mod0, bnrpr, subpr, M, dtQ, p1; GEN cycpr, cycQ; bnf = bnr_get_bnf(bnr); mod = bnr_get_mod(bnr); mod0 = gel(mod,1); v = idealval(bnf, mod0, pr); if (v == 0) { bnrpr = bnr; subpr = subgroup; e = 1; } else { /* part of mod coprime to pr */ GEN mpr0 = idealdivpowprime(bnf, mod0, pr, utoipos(v)); bnrpr = Buchray(bnf, mkvec2(mpr0, gel(mod,2)), nf_INIT|nf_GEN); cycpr = bnr_get_cyc(bnrpr); M = ZM_mul(bnrsurjection(bnr, bnrpr), subgroup); subpr = ZM_hnf(shallowconcat(M, diagonal_shallow(cycpr))); /* e = #(bnr/subgroup) / #(bnrpr/subpr) */ e = itos( diviiexact(ZM_det_triangular(subgroup), ZM_det_triangular(subpr)) ); } /* f = order of [pr] in bnrpr/subpr */ dtQ = InitQuotient(subpr); p1 = ZM_ZC_mul(gel(dtQ,3), isprincipalray(bnrpr, pr)); cycQ = gel(dtQ,2); f = itos( Order(cycQ, p1) ); avma = av; return mkvecsmall2(e, f); } 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); dbg_block(); listCR = get_listCR(bnr, gel(data,3)); dbg_release(); for (av = avma;; avma = av) { gel(data,5) = InitChar(bnr, listCR, dprec); pol = AllStark(data, nf, -1, dprec); pr = nbits2nlong( 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), no prime dividing f splits in the corresponding quadratic extension and m is of minimal norm. Return bnr(m), D, 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, nbp, maxnorm, minnorm, N, nbidnn, s, c, j, 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, bpr, indpr, sgp, p2; sgp = gel(dtQ,4); 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)) ); bpr = divcond(bnr); nbp = lg(bpr) - 1; indpr = cgetg(nbp + 1,t_VECSMALL); for (i = 1; i <= nbp; i++) { GEN ef = GetIndex(gel(bpr,i), bnr, sgp); indpr[i] = ef[1] * ef[2]; } /* 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(dtQ[2]) == 2) iscyc = 1; if (DEBUGLEVEL>1) err_printf("Looking for a modulus of norm: "); for(;;) { dbg_block(); listid = ideallist(nf, maxnorm); /* all ideals of norm <= maxnorm */ dbg_release(); 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 */ dbg_block(); bnrm = Buchray(bnf, m, nf_INIT|nf_GEN); c = bnrisconductor(bnrm, NULL); dbg_release(); 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 */ dbg_block(); candD = subgrouplist_cond_sub(bnrm, ImC, mkvec(gen_2)); dbg_release(); nbcand = lg(candD) - 1; for (c = 1; c <= nbcand; c++) { GEN D = gel(candD,c); long cpl; /* check the splitting of primes */ for (j = 1; j <= nbp; j++) { GEN ef = GetIndex(gel(bpr,j), bnrm, D); if (ef[1] * ef[2] == indpr[j]) break; /* no good */ } if (j <= nbp) 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 = InitRU(den, prec); /* 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(talker,"conductor too large in ArtinNumber"); 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 = const_vecsmall(nz, 0); vN = cgetg(nChar+1, t_VEC); for (ic = 1; ic <= nChar; ic++) gel(vN,ic) = const_vecsmall(nz, 0); av2 = avma; lim = stack_lim(av2, 1); vB = const_vec(nz, gen_1); s0 = powgi(z, modii(gel(vt,1), den)); /* 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)) < bit_accuracy(prec) >> 1) pari_err(bugparier, "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(flagerr,"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(talker, "incorrect character in bnrrootnumber"); 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 p1, 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; p1 = ComputeImagebyChar(chi, isprincipalray(bnrc, pr)); if (flag) B = gsubsg(1, gdiv(p1, pr_norm(pr))); else if (gequal1(p1)) { B = glog(pr_norm(pr), prec); (*r)++; } else B = gsubsg(1, p1); A = gmul(A, B); } return A; } 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(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) */ 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 = ((prec-2) << 1) + EXTRA_PREC; C = gmul2n(sqrtr_abs(divir(dk, powru(mppi(prec2),N))), -r2); initc = init_get_chic( bnr_get_cyc(bnr) ); dbg_block(); dataCR = cgetg_copy(listCR, &l); for (i = 1; i < l; i++) { GEN olddtcr, dtcr = cgetg(9, 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) = gel(cond,1); 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) */ chi = GetPrimChar(chi, bnr, ch_bnr(dtcr), prec2); if (!chi) chi = ch_CHI(dtcr); ch_CHI0(dtcr) = chi; } dbg_release(); 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 = ((prec - 2)<<1) + 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); ch_C(dtcr) = gmul(C, gsqrt(ZM_det_triangular(ch_cond(dtcr)), 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(long x) { double lx = log((double)x); return 1 + (long) (x/lx * (1 + 3/(2*lx))); } static void InitPrimesQuad(GEN bnr, long 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); byteptr d = diffptr + 1; 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); for (p = 2; p <= N0; prime[2] = p) { switch (krois(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; } NEXT_PRIME_VIADIFF(p,d); } /* 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, long N0, LISTray *R) { GEN bnf = bnr_get_bnf(bnr), cond = gel(bnr_get_mod(bnr), 1); long np,p,j,k,l, condZ = itos(gcoeff(cond,1,1)), N = lg(cond)-1; GEN tmpray, tabpr, prime, pr, nf = bnf_get_nf(bnf); byteptr d = diffptr + 1; R->condZ = condZ; l = PiBound(N0) * N; tmpray = cgetg(N+1, t_VEC); R->L1 = vecsmalltrunc_init(l); R->L1ray = vectrunc_init(l); prime = utoipos(2); for (p = 2; p <= N0; prime[2] = p) { pari_sp av = avma; if (DEBUGLEVEL>1 && (p & 2047) == 1) err_printf("%ld ", p); tabpr = idealprimedec(nf, prime); for (j = 1; j < lg(tabpr); j++) { pr = gel(tabpr,j); np = itos_or_0( pr_norm(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)); } NEXT_PRIME_VIADIFF(p,d); } } 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) = gen_0; 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 = gsubst(gam,0,x2); p2 = gdiv(gsubst(gamdm,0,x2), Y); /* Gamma((x-1)/2) */ } else { t = b; s = a; X = gadd(x2,ghalf); Y = x2; p1 = gsubst(gamdm,0,x2); p2 = gsubst(gam,0,x2); } 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, -bit_accuracy(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 = BIGDEFAULTPREC + divsBIL( expi(Bd) ); prec2 = maxss((prec << 1) - 2, 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 = (prec2 << 1) - 2; 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, -bit_accuracy(prec) >> 4); vec = shallowconcat(mkvec(gneg(beta)), row(M, d->v)); imin = (long)bit_accuracy_mul(prec, .225); imax = (long)bit_accuracy_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 (bit_accuracy(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; } /* compute S and T for the quadratic case where the extension is of the type used to construct abelian extensions using Stark units */ static void QuadGetST(GEN bnr, GEN *pS, GEN *pT, GEN dataCR, GEN vChar, long prec) { const long cl = lg(dataCR) - 1; pari_sp av, av1, av2; long ncond, n, j, k, n0; GEN N0, C, T, S, cf, cfh, an, degs; LISTray LIST; pari_timer ti; if (DEBUGLEVEL) timer_start(&ti); /* 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); } av = avma; /* initializations */ degs = GetDeg(dataCR); ncond = lg(vChar)-1; C = cgetg(ncond+1, t_VEC); N0 = cgetg(ncond+1, t_VECSMALL); n0 = 0; for (j = 1; j <= ncond; j++) { GEN dtcr = gel(dataCR, mael(vChar,j,1)), c = ch_C(dtcr); gel(C,j) = c; N0[j] = (long)bit_accuracy_mul(prec, 0.35 * gtodouble(c)); if (n0 < N0[j]) n0 = N0[j]; } if ((ulong)n0 > maxprime()) pari_err(talker, "Not enough precomputed primes (need all p <= %ld)", n0); if (DEBUGLEVEL>1) err_printf("N0 = %ld\n", n0); InitPrimesQuad(bnr, n0, &LIST); cfh = sqrtr(mppi(prec)); cf = gmul2n(cfh, 1); av1 = avma; /* loop over conductors */ for (j = 1; j <= ncond; j++) { GEN c1 = gel(C,j), c2 = divur(2,c1), ec2 = mpexp(c2); GEN LChar = gel(vChar,j); const long nChar = lg(LChar)-1, NN = N0[j]; GEN veint1, vcn; if (DEBUGLEVEL>1) err_printf("* conductor no %ld/%ld (N = %ld)\n\tInit: ", j,ncond,NN); if (lg(ec2) > prec) ec2 = rtor(ec2, prec); veint1 = mpveceint1(rtor(c2, prec), ec2, NN); vcn = mpvecpow(invr(ec2), NN); av2 = avma; for (n=2; n<=NN; n++, avma = av2) affrr(divru(gel(vcn,n), n), gel(vcn,n)); 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); 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(vcn,n))); p2 = gadd(p2, gmul(an, gel(veint1,n))); if (++c == 256) { gerepileall(av2,2, &p1,&p2); c = 0; } } gaffect(gmul(cfh, gmul(p1,c1)), gel(S,t)); gaffect(gmul(cf, gconj(p2)), gel(T,t)); FreeMat(matan,NN); avma = av2; } if (DEBUGLEVEL>1) err_printf("\n"); avma = av1; } avma = av; } /* S & T for the general case */ 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); Z[1] = 0; /* unused */ csurn = divru(T->c1, n); nsurc = invr(csurn); lncsurn = logr_abs(csurn); 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 = gel(A,1); B = gel(bij,i0); s = gel(B,1); for (j = 2; j <= r; j++) { if (signe(B[j])) s = mpadd(s, mulrr(gel(Z,j), gel(B,j))); if (signe(A[j])) t = mpadd(t, mulrr(gel(Z,j), gel(A,j))); } for (i = i0 - 1; i > 1; i--) { A = gel(aij,i); if (signe(t)) t = mulrr(t, nsurc); B = gel(bij,i); if (signe(s)) s = mulrr(s, nsurc); for (j = odd(i)? T->rc2: T->rc1; j > 1; j--) { if (signe(B[j])) s = addrr(s, mulrr(gel(Z,j), gel(B,j))); if (signe(A[j])) t = addrr(t, mulrr(gel(Z,j), gel(A,j))); } if (signe(B[1])) s = addrr(s, gel(B,1)); if (signe(A[1])) t = addrr(t, gel(A,1)); } /* i = 1 */ A = gel(aij,1); if (signe(t)) t = mulrr(t, nsurc); B = gel(bij,1); if (signe(s)) s = mulrr(s, nsurc); if (signe(B[1])) s = addrr(s, gel(B,1)); if (signe(A[1])) t = addrr(t, gel(A,1)); for (j = 2; j <= r; j++) { if (signe(B[j])) s = addrr(s, mulrr(gel(Z,j), gel(B,j))); if (signe(A[j])) t = addrr(t, mulrr(gel(Z,j), gel(A,j))); } s = addrr(s, T->b? mulrr(csurn, gel(T->powracpi,T->b)): csurn); 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 GetST(GEN bnr, GEN *pS, GEN *pT, GEN dataCR, GEN vChar, long prec) { const long cl = lg(dataCR) - 1; pari_sp av, av1, av2; long ncond, n, j, k, jc, n0, prec2, i0, r1, r2; GEN nf, racpi, powracpi; GEN N0, C, T, S, an, degs, limx; LISTray LIST; ST_t cScT; pari_timer ti; if (DEBUGLEVEL) timer_start(&ti); nf = checknf(bnr); /* 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); } av = avma; /* 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, bit_accuracy(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]; } if ((ulong)n0 > maxprime()) pari_err(talker, "Not enough precomputed primes (need all p <= %ld)", n0); i0 = zeta_get_i0(r1, r2, bit_accuracy(prec), limx); InitPrimes(bnr, n0, &LIST); prec2 = ((prec-2) << 1) + 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], 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; if (DEBUGLEVEL>1) err_printf("\tcharacter no: %ld (%ld/%ld)\n", t,k,nChar); 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; } if (DEBUGLEVEL>1) err_printf("\n"); avma = av1; } clear_cScT(&cScT, n0); avma = av; } /*******************************************************************/ /* */ /* 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, polredabs0(T, nf_PARTIALFACT)); } static GEN GenusFieldQuadImag(GEN disc) { long i, l; pari_sp av = avma; GEN T = NULL, P; P = gel(Z_factor(absi(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, polredabs0(T, nf_PARTIALFACT)); } /* 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; W = ComputeAllArtinNumbers(dataCR, vChar, (flag >= 0), newprec); if (DEBUGLEVEL) timer_printf(&ti,"Compute W"); Lp = cgetg(cl + 1, t_VEC); if (!flag) { if (nf_get_degree(nf) == 2) QuadGetST(bnr, &S,&T,dataCR,vChar,newprec); else GetST(bnr, &S, &T, dataCR, vChar, newprec); if (DEBUGLEVEL) timer_printf(&ti, "S&T"); for (i = 1; i <= cl; i++) Lp[i] = GetValue(gel(dataCR,i), gel(W,i), gel(S,i), gel(T,i), 2, newprec)[2]; } 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, bit_accuracy(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(gch(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(precer, "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 = gprecision(polrelnum)-2 - divsBIL( 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 subgp, GEN cyc, const char *s) { if (!subgp || gequal0(subgp)) return cyc; if (typ(subgp) == t_MAT) { RgM_check_ZM(subgp, s); subgp = ZM_hnf(subgp); if (hnfdivide(subgp, cyc)) return subgp; } pari_err(talker,"incorrect subgroup in %s", s); return NULL; } GEN bnrstark(GEN bnr, GEN subgrp, long prec) { long N, newprec; pari_sp av = avma; GEN bnf, p1, Mcyc, 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(talker, "main variable in bnrstark must not be x"); if (nf_get_r2(nf)) pari_err(talker, "base field not totally real in bnrstark"); Mcyc = diagonal_shallow(bnr_get_cyc(bnr)); subgrp = get_subgroup(subgrp,Mcyc,"bnrstark"); /* compute bnr(conductor) */ p1 = bnrconductor(bnr, subgrp, 2); bnr = gel(p1,2); Mcyc = diagonal_shallow(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(talker, "class field not totally real in bnrstark"); /* 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++) { GEN t = gel(M,i); if (is_pm1(gel(cyc,i))) continue; gel(M,i) = gel(Mcyc,i); H = ZM_hnf(shallowconcat(M, Mcyc)); gel(M,i) = t; 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 bnf, nf, cyc, L1, lchi, clchi, allCR, listCR, dataCR; GEN W, S, T, indCR, invCR, Qt, vChar; long N, cl, i, j, nc, a; pari_sp av = avma; checkbnr(bnr); bnf = bnr_get_bnf(bnr); nf = bnf_get_nf(bnf); N = nf_get_degree(nf); if (N == 1) pari_err(talker, "the ground field must be distinct from Q"); if (flag < 0 || flag > 8) pari_err(flagerr,"bnrL1"); /* compute bnr(conductor) */ if (!(flag & 2)) bnr = gel(bnrconductor(bnr, NULL, 2),2); cyc = bnr_get_cyc(bnr); subgp = get_subgroup(subgp, diagonal_shallow(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) */ lchi = LiftChar(cyc, gel(Qt,3), gel(allCR,i), gel(Qt,2)); clchi = ConjChar(lchi, cyc); 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); if (nc == 0) pari_err(talker, "no non-trivial character in bnrL1"); /* compute the data for these characters */ dataCR = InitChar(bnr, listCR, prec); vChar = sortChars(dataCR); GetST(bnr, &S, &T, dataCR, vChar, prec); W = ComputeAllArtinNumbers(dataCR, vChar, 1, prec); L1 = cgetg((flag&1)? cl: cl+1, t_VEC); for (i = 1; i < cl; i++) { 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(bugparier,"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; dbg_block(); if (v == NO_VARIABLE) v = fetch_user_var("y"); bnf = Buchall(quadpoly0(D, v), nf_FORCE, prec); dbg_release(); nf = bnf_get_nf(bnf); isfund = equalii(D, nf_get_disc(nf)); } else isfund = Z_isfundamental(D); if (!isfund) pari_err(talker,"quadray needs a fundamental discriminant"); } else { bnf = checkbnf(D); nf = bnf_get_nf(bnf); if (nf_get_degree(nf) != 2) pari_err(talker,"not a polynomial of degree 2 in quadray"); 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; CATCH(precer) { 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); } 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; } CATCH_RELEASE(); 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); } ENDCATCH; if (pol) { pol = makescind(nf, pol); return gerepileupto(av, polredabs0(pol, nf_PARTIALFACT)); } } } /*******************************************************************/ /* */ /* 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; 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) */ long i, l = 1; double best = 0.; ulong q = 0, maxq = maxprime(); byteptr d = diffptr; if (maxq > 50000) maxq = 50000; T->D = D; T->p = T->q = 0; for(;;) { GEN Q; long gcdq, mod; int order2, store; double t; NEXT_PRIME_VIADIFF_CHECK(q, d); if (best > 0 && q >= maxq) { if (DEBUGLEVEL) pari_warn(warner,"possibly suboptimal (p,q) for D = %Ps", D); break; } if (krois(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(bugparier, "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 = 3; 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) + nbits2nlong(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(bugparier,"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)> bit_accuracy(minss(prec,lg(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 = (prec<<1)-2; 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++) if (signe(y[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.5.5/src/modules/galpol.c0000644000175000017500000000344412147140047014772 0ustar billbill/* $Id$ 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 = stackmalloc(strlen(pari_datadir) + 11 + 20 + 1); sprintf(s,"%s/galpol/%ld/nb", pari_datadir, a); F = pari_fopengz(s); if (!F) pari_err(talker,"Missing galpol file %s\n",s); n = gp_read_stream(F->file); if (!n || typ(n)!=t_INT) pari_err(talker,"Incompatible galpol file %s\n",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 || b<0) pari_err(talker,"argument must be positive"); if (!b) return galoisnbpol(a); switch(sig) { case 1: si="real"; break; case 2: if (a%2==0) { si="complex"; break; } default: /*FALL THROUGH*/ pari_err(talker,"invalid signature in galoisgetpol"); return NULL; } s = pari_sprintf("%s/galpol/%ld/%ld/%s", pari_datadir, a,b,si); F = pari_fopengz(s); free(s); if (!F) { long n = itos(galoisnbpol(a)); if (b>n) pari_err(talker,"Only %ld group%s of order %ld",n,n>2?"s":"",a); else pari_err(talker,"Missing galpol file"); } V = gp_read_stream(F->file); if (!V || typ(V)!=t_VEC ) pari_err(talker,"Incompatible galpol file\n"); pari_fclose(F); return V; } pari-2.5.5/src/modules/subfield.c0000644000175000017500000006521612147140047015316 0ustar billbill/* $Id$ 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 = divisors(utoipos(n[1])); lK = lg(K); for (i=1; isize*k, lpn = 0; for (j=2; j= BIL) pari_err(talker,"overflow in 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), 2); 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 = gmul(gneg(h0), ZX_Z_divexact(a, p)); w1 = gadd(w0, gmul(p, FpXQ_red(a, T,p))); w1_Q = centermod(gmul(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 = gmul(gneg(h0), FpX_FpXQV_eval(gp, FpXV_red(wpow,q),T,q)); a = ZX_Z_add(FpX_rem(a, T,q), gen_1); /* 1 - h0 g'(w1) = 0 (p) */ a = gmul(h0, ZX_Z_divexact(a, p)); h0 = gadd(h0, gmul(p, FpXQ_red(a, T,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(talker, "relatively prime polynomials expected"); 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), T, p); gel(S->interp,j) = interpol(F,T,p); S->firstroot[j] = l; for (i=1; ifk[l] = F[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) { byteptr di = diffptr + 1; long i, j, k, r, lcm, oldlcm, pp, N = degpol(pol), minp = N*N / 4; GEN Z, p, ff, oldff, n, oldn; pari_sp av; p = utoipos(2); while (p[2] <= minp) NEXT_PRIME_VIADIFF(p[2], di); oldlcm = 0; oldff = oldn = NULL; pp = 0; /* gcc -Wall */ av = avma; for(k = 1; k < 11 || !oldlcm; k++,avma = av) { do NEXT_PRIME_VIADIFF(p[2], di); while (!smodis(dpol, p[2])); if (k > 5 * N) pari_err(talker,"sorry, too many block systems in nfsubfields"); ff = gel(FpX_factor(pol, 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[2],lcm,n); pp = p[2]; oldn = n; oldff = ff; oldlcm = lcm; if (r == 1) break; av = avma; } if (DEBUGLEVEL) err_printf("Chosen prime: p = %ld\n", pp); 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(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,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 = itos(gel(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; 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(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); } /* globfa contains the odd prime divisors of e(t) */ static GEN e(ulong t, GEN *globfa) { GEN fa, P, E, s, Primes; ulong nbd, m, k, d; long lfa, i, j; fa = factoru(t); P = gel(fa,1); E = gel(fa,2); lfa = lg(P); nbd = 1; for (i=1; i 5000000) return gen_0; if (d != 2) vecsmalltrunc_append(Primes, d); s = muliu(s, upowuu(d, 1 + u_lval(t,d))); } } if (globfa) { vecsmall_sort(Primes); *globfa = Primes; } return s; } static ulong compt(GEN N) { pari_sp av0 = avma; double Cd = 100 * rtodbl(logr_abs(itor(N,DEFAULTPREC))) / log(10.); ulong t, C = (ulong)ceil(Cd); GEN B; avma = av0; /* C < [200*log_10 e(t)] ==> return t. For e(t) < 10^529, N < 10^1058 */ if (C < 540) return 6; if (C < 963) return 12; if (C < 1023) return 24; if (C < 1330) return 48; if (C < 1628) return 36; if (C < 1967) return 60; if (C < 2349) return 120; if (C < 3083) return 180; if (C < 3132) return 240; if (C < 3270) return 504; if (C < 3838) return 360; if (C < 4115) return 420; if (C < 4621) return 720; if (C < 4987) return 840; if (C < 5079) return 1440; if (C < 6212) return 1260; if (C < 6686) return 1680; if (C < 8137) return 2520; if (C < 8415) return 3360; if (C < 10437) return 5040; if (C < 11643) return 13860; if (C < 12826) return 10080; if (C < 13369) return 16380; if (C < 13540) return 21840; if (C < 15060) return 18480; if (C < 15934) return 27720; if (C < 17695) return 32760; if (C < 18816) return 36960; if (C < 21338) return 55440; if (C < 23179) return 65520; if (C < 23484) return 98280; if (C < 27465) return 110880; if (C < 30380) return 131040; if (C < 31369) return 166320; if (C < 33866) return 196560; if (C < 34530) return 262080; if (C < 36195) return 277200; if (C < 37095) return 360360; if (C < 38179) return 480480; if (C < 41396) return 332640; if (C < 43301) return 554400; if (C < 47483) return 720720; if (C < 47742) return 665280; if (C < 50202) return 831600; if (C < 52502) return 1113840; if (C < 60245) return 1441440; if (C < 63112) return 1663200; if (C < 65395) return 2227680; if (C < 69895) return 2162160; if (C < 71567) return 2827440; if (C < 75708) return 3326400; if (C < 79377) return 3603600; if (C < 82703) return 6126120; if (C < 91180) return 4324320; if (C < 93978) return 6683040; if (C < 98840) return 7207200; if (C < 99282) return 11138400; if (C < 105811) return 8648640; B = sqrti(N); for (t = 8648640+840;; t+=840) { pari_sp av = avma; if (cmpii(e(t, NULL), B) > 0) break; avma = av; } avma = av0; 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 = const_vecsmall(pk, 0); 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; ulong x, pk, i, qs2; if (k == 1) return NULL; T = computetabdl(q); /* could store T[x+1] + T[x] + qs2 (cf compute_g). * Recompute instead, saving half the memory. */ pk = 1UL << k;; vpk = const_vecsmall(pk, 0); 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; } static void calcjac(Cache **pC, GEN globfa, GEN *ptabfaq, GEN *ptabj) { GEN J, tabg, faq, tabfaq, tabj, P, PE; long lfaq, j; ulong i, q, l; pari_sp av; l = lg(globfa); *ptabfaq = tabfaq= cgetg(l,t_VEC); *ptabj = tabj = cgetg(l,t_VEC); for (i=1; iavite) { 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*)new_chunk(sizeof(Cache) / sizeof(long)); C->matvite = NULL; C->avite = NULL; C->ctsgt = 0; return C; } static Cache ** calcglobs(Red *R, ulong t, long *pltab, GEN *pP) { GEN fat, P, E, PE; long lv, lfa, pk, p, e, i, k; long ltab, b; Cache **pC; b = bit_accuracy(lgefint(R->N)) - 1; while ( !bittest(R->N,b) ) b--; b++; k = 3; while (((k+1)*(k+2) << (k-1)) < b) k++; *pltab = ltab = (b/k) + 2; R->k = k; R->lv = 1L << (k-1); R->mask = (1UL << k) - 1; fat = factoru_pow(t); P = gel(fat,1); lfa = lg(P); E = gel(fat,2); PE= gel(fat,3); lv = 1; for (i=1; i lv) lv = pe; } pC = (Cache**)cgetg(lv + 1, t_VEC); 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 jpq) { const long pk = upowuu(p,k); long ind; GEN s1, s2, s3; if (!jpq) jpq = get_jac(C, q, pk, compute_g(q)); 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; } /* return 1 [OK so far] or <= 0 [not a prime] */ static long step5(Cache **pC, Red *R, long p, GEN et, ulong ltab) { pari_sp av; ulong ct = 1, q; long pk, k, fl = -1; byteptr d = diffptr+2; Cache *C, *Cp; for (q = 3; *d; ) { if (q%p != 1 || umodiu(et,q) == 0) goto repeat; if (umodiu(R->N,q) == 0) return -1; k = u_lval(q-1, p); pk = upowuu(p,k); if (pk < lg(pC) && pC[pk]) { C = pC[pk]; Cp = pC[p]; } else { C = pC[1]; C->matvite = NULL; /* re-init */ Cp = NULL; } if (!filltabs(C, Cp, R, p, pk, ltab)) return 0; av = avma; 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 (long)(-q); if (fl == 1) return ct; avma = av; ct++; repeat: NEXT_PRIME_VIADIFF(q,d); } pari_err(bugparier,"aprcl test fails! this is highly improbable"); return 0; } 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("Jacobi sums and tables computed\n"); err_printf("Step4: q-values (# = %ld): ", l-1); } for (i=l-1; i>0; i--) { GEN faq = gel(tabfaq,i), P = gel(faq,1), E = gel(faq,2), PE = gel(faq,3); long lfaq = lg(P); q = globfa[i]; if (DEBUGLEVEL>2) err_printf("%ld ",q); for (j=1; jcyc; if (p >= 3) fl = step4a(C,&R, q,p,e, gmael(tabj,i,j)); 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[p] = 1; } } if (DEBUGLEVEL>2) err_printf("\nStep5: testing conditions lp\n"); for (i=1; i ctglob) ctglob = fl; /* DEBUG */ } if (DEBUGLEVEL>2) err_printf("Step6: testing potential divisors\n"); res = step6(N, t, et); if (DEBUGLEVEL>2) { 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("Maximal number of nondeterministic steps = %lu\n",ctglob); } return res; } long isprimeAPRCL(GEN N) { pari_sp av = avma; GEN res = aprcl(N); avma = av; return (typ(res) == t_INT); } pari-2.5.5/src/modules/thue.c0000644000175000017500000011726412147140047014467 0ustar billbill/* $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. */ #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(tnf[1]) != t_VEC) return 0; if (l != 8) return 1; /* S=0 */ (void)checkbnf(gel(tnf,2)); return (typ(tnf[3]) == t_COL && typ(tnf[4]) == t_COL && typ(tnf[5]) == t_MAT && typ(tnf[6]) == t_MAT && typ(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)); } /* Returns the index of the largest element in a vector */ static GEN _Vecmax(GEN Vec, long *ind) { long k, tno = 1, l = lg(Vec); GEN tmax = gel(Vec,1); for (k = 2; k < l; k++) if (gcmp(gel(Vec,k),tmax) > 0) { tmax = gel(Vec,k); tno = k; } if (ind) *ind = tno; return tmax; } static GEN Vecmax(GEN v) { return _Vecmax(v, NULL); } static long Vecmaxind(GEN v) { long i; (void)_Vecmax(v, &i); return i; } static GEN tnf_get_roots(GEN poly, long prec, long S, long T) { GEN R0 = cleanroots(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) { if (!gequal1(leading_term(P))) pari_err(talker,"non-monic polynomial in thue"); 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 = (prec_roots << 1) - 2; 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 = gen_1; 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(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) = roundr(negr(mulir(C, BS->lambda))); gcoeff(lllmat, 3, 2) = roundr(negr(mulir(C, BS->delta))); 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; x = gadd(z1, gmul(ro1, y)); x = grndtoi(real_i(x), &e); if (e > 0) return 0; if (e <= -13) { check_sol( x , y, P,rhs,pS); check_sol(negi(x), negi(y), P,rhs,pS); } 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; } /* Check for not-so-small solutions */ 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 = (expo(bound) > 30)? ceil_safe(bound): floorr(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(RgX_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); } if (signe(z) == signe(rhs)) { add_sol(pS, p, q); if (!odd(d)) add_sol(pS, negi(p), negi(q)); } else if (odd(d)) add_sol(pS, negi(p), negi(q)); } } if (j == lg(t)) pari_err(bugparier, "Short continued fraction in thue"); } 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 = itou(floorr(x3)); if (DEBUGLEVEL>1) err_printf("* Checking for small solutions <= %lu\n", By); /* 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"); S = gerepilecopy(av, S); 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(notpoler,"thueinit"); dpol = degpol(pol); if (dpol <= 0) pari_err(constpoler,"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 = lg(gel(fa,1)); 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_user_var("y_"); long va = fetch_user_var("a_"); long vb = fetch_user_var("b_"); if (e != 1) { if (lfa == 2) { tnf = mkvec2(mkvec3(pol,C,L), mkvec2(thueinit(f, flag, prec), E)); 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)); return gerepilecopy(av, tnf); } if (dpol <= 2) pari_err(talker,"invalid polynomial in thue (need deg>2)"); 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 = 3 + (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)) / ((sizeof(long)/4)* 10.)); 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 = (PREC<<1)-2; 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), bit_accuracy(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(bugparier,"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); long cf; for (cf = 0; cf < 10; cf++, kappa = muliu(kappa,10)) { int res = LLL_1stPass(&B0, kappa, BS, &Bx); if (res) break; if (DEBUGLEVEL>1) err_printf("LLL failed. Increasing kappa\n"); } /* FIXME: TO BE COMPLETED */ if (!step && cf == 10) { /* 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(bugparier,"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(typeer, "thue"); 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(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(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 = (prec<<1)-2; 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(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 = Vecmaxind(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 += 5 * (DEFAULTPREC-2); if (DEBUGLEVEL>1) pari_warn(warnprec,"thue",prec); tnf = inithue(P, bnf, 0, prec); 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 (!checktnf(tnf)) pari_err(talker,"not a tnf in thue"); if (typ(rhs) != t_INT) pari_err(typeer,"thue"); /* 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(talker,"infinitely many solutions in thue"); 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); if (!odd(e)) { Rab = gsubst(gsubst(R, va, negi(df)), vb, negi(dg)); ry = nfrootsQ(Rab); for (k = 1; k < lg(ry); k++) if (typ(gel(ry,k)) == t_INT) check_y(&S, P, POL, gel(ry,k), rhs); } } } 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 = Z_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(typeer,"bnfisintnormabs"); 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, absi(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.5.5/src/modules/DedekZeta.c0000644000175000017500000004265212147140047015360 0ustar billbill/* $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. */ /*******************************************************************/ /* */ /* DEDEKIND ZETA FUNCTION */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" static GEN dirzetak0(GEN nf, ulong N) { GEN vect, c, c2, pol = nf_get_pol(nf), index = nf_get_index(nf); pari_sp av = avma; const ulong SQRTN = (ulong)(sqrt(N) + 1e-3); ulong i, p, lx; byteptr d = diffptr; long court[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0}; (void)evallg(N+1); c = cgetalloc(t_VECSMALL, N+1); c2 = cgetalloc(t_VECSMALL, N+1); c2[1] = c[1] = 1; for (i=2; i<=N; i++) c[i] = 0; maxprime_check(N); for (p = 0; p <= N; avma = av) { NEXT_PRIME_VIADIFF(p, d); court[2] = p; if (umodiu(index, p)) /* court does not divide index */ { vect = gel(FpX_degfact(pol,court),1); lx = lg(vect); } else { GEN P = idealprimedec(nf,court); lx = lg(P); vect = cgetg(lx,t_VECSMALL); for (i=1; i 0) break; qn = q = (ulong)NP[2]; 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 */ while (qn <= (ulong)N) { ulong k, k2; /* k2 = k*qn */ LOCAL_HIREMAINDER; for (k = N/qn, k2 = k*qn; k > 0; k--, k2 -=qn) c2[k2] += c[k]; qn = mulll(qn, q); if (hiremainder) break; } swap(c, c2); } else /* p > sqrt(N): much 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]; } } pari_free(c2); return c; } GEN dirzetak(GEN nf, GEN b) { GEN z, c; long n; if (typ(b) != t_INT) pari_err(talker,"not an integer type in dirzetak"); if (signe(b) <= 0) return cgetg(1,t_VEC); nf = checknf(nf); n = itos_or_0(b); if (!n) pari_err(talker,"too many terms in 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); setexpo(p2, expo(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(talker, "need %Ps coefficients in initzeta: computation impossible", z); 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 = bit_accuracy(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 = (prec<<1) - 2; 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 = lg(gel(C,1))-1; 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 = lg(gel(C,1))-1; 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(znf[1]) != t_VECSMALL) pari_err(talker,"not a zeta number field in zetakall"); if (isint(s, &s)) { long ss = itos(s), r1, r2; if (ss==1) pari_err(talker,"s = 1 is a pole (gzetakall)"); znf_get_sign(znf, &r1, &r2); if (ss==0) { avma = av; if (flag) pari_err(talker,"s = 0 is a pole (gzetakall)"); 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+1); } else z = cxlambdak(znf, s, flag, prec+1); 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.5.5/src/modules/mpqs.c0000644000175000017500000035531412147140047014502 0ustar billbill/* $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. */ /* 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" #ifdef ENABLE_TLS static THREAD char *saveptr; #define strtok(x,y) strtok_r(x,y,&saveptr) #endif /** 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; #ifdef MPQS_DEBUG_VERBOSE err_printf("MPQS DEBUG: FB chunk allocated @0x%p\n", (void *)fbp); err_printf("MPQS DEBUG: FB aligned to 0x%p\n", (void *)fbl); #endif iahl = (((long)iahp) + 64) & ~0x3FL; h->inv_A_H = (mpqs_inv_A_H_t *)iahl; #ifdef MPQS_DEBUG_VERBOSE err_printf("MPQS DEBUG: inv_A_H chunk allocated @0x%p\n", (void *)iahp); err_printf("MPQS DEBUG: inv_A_H aligned to 0x%p\n", (void *)iahl); #endif 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)); #ifdef MPQS_DEBUG_VERBOSE err_printf("MPQS DEBUG: sieve_array allocated @0x%p\n", (void *)h->sieve_array); #endif 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)); #ifdef MPQS_DEBUG_VERBOSE err_printf("MPQS DEBUG: candidates table allocated @0x%p\n", (void *)h->candidates); #endif /* 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 **/ /** **/ /*********************************************************************/ /* our own pointer to PARI's or to our own prime diffs table. * NB the latter is never freed, unless we need to replace it with * an even larger one. */ static THREAD byteptr mpqs_diffptr = NULL; static THREAD long mpqs_prime_count = 0; static THREAD int mpqs_use_our_diffptr = 0; /* return next prime larger than p, using *primes_ptr on the diffptr table * first and pari's other wits after that */ static byteptr mpqs_iterate_primes(ulong *p, byteptr primes_ptr) { ulong prime = *p; if (*primes_ptr) NEXT_PRIME_VIADIFF(prime,primes_ptr); else prime = unextprime(prime+1); *p = prime; return primes_ptr; } /* fill in the best-guess multiplier k for N. We force kN = 1 mod 4. * Caller should proceed to fill in kN */ static void mpqs_find_k(mpqs_handle_t *h) { pari_sp av = avma; const mpqs_multiplier_t *cand_k; long best_i = -1 /* never best */, k, N_mod_4 = mod4(h->N); ulong p; GEN kN; double best_value = -1000. /* essentially -infinity */, value, dp; long i, j; byteptr primes_ptr; for (i = 0; i < MPQS_POSSIBLE_MULTIPLIERS; i++) { cand_k = &cand_multipliers[i]; k = cand_k->k; if ((k & 3) == N_mod_4) /* kN = 1 (mod 4) */ { value = -0.7 * log2 ((double) k); kN = muliu(h->N, k); if (mod8(kN) == 1) value += 1.38629; j = 0; p = 0; primes_ptr = diffptr; /* that's PARI's, not our private one */ while (j <= MPQS_MULTIPLIER_SEARCH_DEPTH) { primes_ptr = mpqs_iterate_primes(&p, primes_ptr); if (krouu(umodiu(kN, p), p) == 1) { j++; dp = log2((double) p) / p; value += (k % p == 0) ? dp : 2 * dp; } } if (value > best_value) { best_value = value; best_i = i; } } } avma = av; h->_k = cand_multipliers[best_i]; } /******************************/ /* guesstimate up to what size we're going to need precomputed small primes */ static long mpqs_find_maxprime(long size) { double x; if (size < 16000) return 176000; x = log((double)size); x += log(x) - 0.9427; return (long)(x * size); } /* return the number of primes in mpqs_diffptr */ static long mpqs_count_primes(void) { byteptr p = mpqs_diffptr; long gaps = 0; for ( ; *p; p++) if (*p == DIFFPTR_SKIP) gaps++; return (p - mpqs_diffptr - gaps); } /* 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 (such a factor necessarily fits into a C long). * We use PARI's normal diffptr array if it's large enough, or otherwise * our own because we don't want to pull out PARI's array under our caller * if someone was in the middle of using it while calling us. (But note * that this makes ourselves non-reentrant.) */ /* TODO: convert (everything!) to new FB entry format */ /* TODO: also fill in a number of other FB entry fields */ /* returns the FB array pointer for convenience */ static mpqs_FB_entry_t * mpqs_create_FB(mpqs_handle_t *h, ulong *f) { ulong p = 0; mpqs_int32_t size = h->size_of_FB; long i, kr /* , *FB */; mpqs_uint32_t k = h->_k.k; mpqs_FB_entry_t *FB; /* for ease of reference */ byteptr primes_ptr; FB = mpqs_FB_ctor(h); /* tentatively pick up PARI's current differences-of-small-primes array * unless we already have our own */ if (!mpqs_use_our_diffptr) mpqs_diffptr = diffptr; if ((mpqs_prime_count? mpqs_prime_count: mpqs_count_primes()) < 3 * size) { /* not large enough - must use our own then */ long newsize = 3 * mpqs_find_maxprime(size); if (mpqs_use_our_diffptr) pari_free((void *) mpqs_diffptr); if (DEBUGLEVEL >= 2) err_printf("MPQS: precomputing auxiliary primes up to %ld\n", newsize); /* the following three assignments must happen in this order, to * safeguard against corruption when we are being interrupted at * the wrong moment: */ mpqs_diffptr = initprimes(newsize); mpqs_use_our_diffptr = 1; /* and will remain true forever */ mpqs_prime_count = mpqs_count_primes(); /* count once and remember */ } if (MPQS_DEBUGLEVEL >= 7) err_printf("MPQS: FB [-1,2"); 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; primes_ptr = mpqs_diffptr; primes_ptr = mpqs_iterate_primes(&p, primes_ptr); /* move past 2 */ /* 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) { primes_ptr = mpqs_iterate_primes(&p, primes_ptr); if ((p > k) || (k%p != 0)) { ulong kN_mod_p = umodiu(h->kN, p); kr = krouu(kN_mod_p, p); if (kr != -1) { if (kr == 0) { if (MPQS_DEBUGLEVEL >= 7) err_printf(",%lu...] Wait a second --\n", p); *f = p; return FB; } if (MPQS_DEBUGLEVEL >= 7) err_printf(",%lu", p); 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 for * it depends on the largest prime in FB, which we're still in the * process of finding here! */ /* x_i such that x_i^2 = (kN % p_i) mod p_i */ FB[i++].fbe_sqrt_kN = (mpqs_uint32_t) Fl_sqrt(kN_mod_p, p); } } } if (MPQS_DEBUGLEVEL >= 7) err_printf("]\n"); FB[i].fbe_p = 0; /* sentinel */ h->largest_FB_p = FB[i-1].fbe_p; /* at subscript size_of_FB + 1 */ #ifdef MPQS_EXPERIMENTAL_COUNT_SIEVE_HITS /* temporary addition: ------------8<---------------------- */ { double hitsum; long j; for (j = 300; j <= 1000; j += 100) { hitsum = 0.; for (i = j; i < size + 2; i++) { p = FB[i].fbe_p; if (p == 0) break; hitsum += ((4.0 * h->M) / p); } err_printf("MPQS DEBUG: hits from FB[%d]=%ld up: %10.2f\n", j, (long)(FB[j].fbe_p), hitsum); } } #endif /* 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; /* assert: 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'll stay away a bit from that. * The highest admissible, in a pinch, 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 very slightly below this. Moreover, the * selection of the individual primes happens to pari_err on the large side, for * which it is wise to compensate a bit. This is what the (small positive) * quantity MPQS_A_FUDGE is for. * We rely on a few auxiliary fields in the handle to be already set by * mqps_set_sieve_threshold() before we are called. * This function may fail under highly unfortunate circumstances, so we * report back about our success to the caller (mpqs()), allowing it to * bail out after emitting a warning. */ 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; } /* GN 20050723 - comparison against index1_FB removed. */ 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 = stackmalloc(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(talker, "error whilst writing to file %s", 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**) stackmalloc(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(talker,"MPQS: relations file truncated?!\n"); 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(talker, "cannot rename file %s to %s", TMP_str, 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(bugparier, "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; #ifdef MPQS_DEBUG GEN C = h->C; #endif 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); GEN p_e, N = h->N, prod = gen_1; long i; mpqs_FB_entry_t *FB = h->FB; s = strtok(t, " \n"); while (s != NULL) { e = atol(s); if (!e) break; s = strtok(NULL, " \n"); i = atol(s); /* special case -1 */ if (i == 1) { prod = subii(N, prod); s = strtok(NULL, " \n"); continue; } p_e = Fp_powu(utoipos(FB[i].fbe_p), (ulong)e, N); prod = remii(mulii(prod, p_e), N); s = strtok(NULL, " \n"); } 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(talker, "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(talker, "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]; long e; strcpy(b, r); s = strtok(b, " \n"); while (s != NULL) { e = atol(s); if (!e) break; s = strtok(NULL, " \n"); ei[ atol(s) ] += e; s = strtok(NULL, " \n"); } } 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(talker, "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 (opened by caller). * 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(FILE *FREL, long rows, long cols, long *fpos) { long i = 0, 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); if ((fpos[0] = ftell(FREL)) < 0) pari_err(talker, "ftell error on full relations file"); while (fgets(buf, MPQS_STRING_LENGTH, FREL)) { s = strchr(buf, ':') + 2; s = strtok(s, " \n"); while (s != NULL) { e = atol(s); if (!e) break; s = strtok(NULL, " \n"); p = atol(s); if (e & 1) F2m_set(m, p, i+1); s = strtok(NULL, " \n"); } i++; if (i < cols && (fpos[i] = ftell(FREL)) < 0) pari_err(talker, "ftell error on full relations file"); } if (i != cols) { err_printf("MPQS: full relations file %s than expected", i > cols ? "longer" : "shorter"); pari_err(talker, "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; s = strchr(rel, ':') - 1; *s = '\0'; res = remii(mulii(Y_prod, strtoi(rel)), N); s = strtok(s + 3, " \n"); while (s != NULL) { long e = atol(s), i; if (!e) break; s = strtok(NULL, " \n"); i = atol(s); /* bug in g++-3.4.1: miscompiles ei[ atol(s) ] */ ei[i] += e; s = strtok(NULL, " \n"); } return gerepileuptoint(av, res); } static char* mpqs_get_relation(char *buf, long pos, FILE *FREL) { if (fseek(FREL, pos, SEEK_SET)) pari_err(talker, "cannot seek FREL file"); if (!fgets(buf, MPQS_STRING_LENGTH, FREL)) pari_err(talker, "FREL file truncated?!"); 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) { FILE *FREL = pFREL->file; 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(FREL, 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], FREL)); 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(bugparier, "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); mpqs_find_k(handle); 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) { if (DEBUGLEVEL >= 4) err_printf("\nMPQS: found factor = %ld whilst creating factor base\n", 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.5.5/src/modules/galois.c0000644000175000017500000017461712212130371014775 0ustar billbill/* $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. */ /**************************************************************/ /* */ /* Galois group for degree between 8 and 11 (included) */ /* */ /**************************************************************/ #include "pari.h" #include "paripriv.h" #define NMAX 11 /* maximum degree */ typedef char IND; typedef IND *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, IND a,...) { static IND x[NMAX+1]; va_list args; long i; va_start(args, a); x[0] = (IND)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)stackmalloc((n1+1) * sizeof(IND)); for (i=1; i<=n1; i++) s3[i] = s1[(int)s2[i]]; s3[0] = (IND)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; byteptr d = diffptr; GEN p1, dtyp; ulong p = 0; 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 */ } 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(talker,"too large precision in fixprec()"); 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)? lg(x[1]): lg(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*) stackmalloc( (m+1)*sizeof(PERM) + (n+1)*m * sizeof(IND) ); 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]=(char)n; return gr; } static pariFILE * galopen(const char *pre, long n, long n1, long n2) { pari_sp av = avma; char *s = stackmalloc(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(talker,"galois files not available\n[missing %s]",s); avma = av; return f; } static char bin(char c) { if (c>='0' && c<='9') c=c-'0'; else if (c>='A' && c<='Z') c=c-'A'+10; else if (c>='a' && c<='z') c=c-'a'+36; else pari_err(talker,"incorrect value in bin()"); 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) { char ch[BUFFS]; long i,j, k = BUFFS; i = j = 1; for(;;) { if (k==BUFFS) { (void)fread(ch,sizeof(char),BUFFS, f->file); k=0; } g[i][j] = bin(ch[k++]); if (++j>m) { j=1; if (++i>n) break; } } 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); (void)fread(&c,sizeof(char), 1, f->file); m=bin(c); (void)fread(&c,sizeof(char), 1, f->file); (void)fread(ch,sizeof(char), 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); (void)fread(ch,sizeof(char),5,f->file); nm = atol(ch); (void)fread(ch,sizeof(char),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,(int)bb[i]); if (typ(t) == t_COMPLEX && signe(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(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(c[2]) != signe(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(talker,"indefinite invariant polynomial in gpoly()"); 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(bugparier,"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(cleanroots(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[ (int)S1[(int)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_accuracy( lg(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 += nbits2nlong(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 (lg(r[1])-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, (int)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 = stackmalloc(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(talker,"galois files %s not compatible\n",s); pari_fclose(f); return gerepilecopy(av, gel(V,k)); } 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 = (long)(cauchy_bound(pol) / (LOG2 * BITS_IN_LONG)) + prec; BR.prmax = BR.pr + BIGDEFAULTPREC-2; BR.N = N; BR.r = vectrunc_init(N+1); r = gclone ( cleanroots(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.5.5/src/modules/ellsea.c0000644000175000017500000013270612147140047014765 0ustar billbill/* $Id$ 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. */ #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 GEN get_seadata(ulong ell) { pari_sp av=avma; GEN eqn; char *s = pari_sprintf("%s/seadata/sea%ld", pari_datadir, ell); pariFILE *F = pari_fopengz(s); free(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 */ static GEN list_to_pol(GEN list, long vx, long vy) { pari_sp ltop = avma; long i, l = lg(list); GEN P = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(P, i) = gtopoly(gel(list,i), vy); return gerepileupto(ltop, gtopoly(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(talker,"ellmodulareqn requires the package seadata"); if (idx && idxtype = *GSTR(gel(eqn, 2)); M->eq = list_to_pol(gel(eqn, 3), vx, vy); return 1; } GEN ellmodulareqn(long ell, long vx, long vy) { struct meqn meqn; GEN res; if (vx<0) vx=0; if (vy<0) vy=fetch_user_var("y"); if (varncmp(vx,vy)>=0) pari_err(talker,"wrong variable priority"); if (ell<0) pari_err(talker,"level must be positive"); if (!uisprime(ell)) pari_err(talker,"level must be prime"); res = cgetg(3, t_VEC); if (!get_modular_eqn(&meqn, ell, vx, vy)) pari_err(talker,"modular equation of level %ld is not available", ell); else { gel(res,1) = meqn.eq; gel(res,2) = stoi(meqn.type=='A'); } return res; } /*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 p, long precS) { GEN res = cgetg(precS+1, t_VEC); long k, h; if (precS == 0) return res; gel(res, 1) = Fp_div(a4, stoi(-5), p); if (precS == 1) return res; gel(res, 2) = Fp_div(a6, stoi(-7), p); for (k = 3; k <= precS; ++k) { pari_sp btop = avma; GEN a = gen_0; for (h = 1; h <= k-2; h++) a = Fp_add(a, Fp_mul(gel(res, h), gel(res, k-1-h), p), p); a = Fp_div(Fp_mulu(a, 3, p), utoi((k-2) * (2*k + 3)), p); gel(res, k) = gerepileuptoint(btop, a); } return res; } /*Computes the n-division polynomial modulo the polynomial h \in Fp[x] */ static GEN a4a6_divpolmod(GEN a4, GEN a6, long n, GEN h, GEN p) { pari_sp ltop = avma; GEN f, f2, ff, rhs, inv2y, a42, res; long N, m, l; if (n <= 2) return n==1 ?gen_1: gen_2; N = maxss(5, (n+1)/2 + 3); f = cgetg(N+1, t_VEC); f2 = cgetg(N+1, t_VEC); /*f2[m]=f[m]^2 */ ff = cgetg(N+1, t_VEC); /*ff[m]=f[m]*f[m-2] */ rhs = FpX_rem(mkpoln(4, gen_1, gen_0, a4, a6), h, p); inv2y = FpXQ_inv(FpX_Fp_mul(rhs, gen_2, p), h, p); gel(f, 2) = scalarpol(gen_2,0); gel(f2, 2) = FpX_Fp_mul(rhs, utoi(4), p); a42 = Fp_sqr(a4, p); gel(f, 3) = FpX_rem(mkpoln(5, utoi(3), gen_0, Fp_mul(utoi(6), a4, p), Fp_mul(utoi(12), a6, p), Fp_neg(a42, p)), h, p); if (n == 3) return gerepileupto(ltop, gel(f, 3)); gel(f, 4) = FpX_rem(FpX_Fp_mul(mkpoln(7, gen_1, gen_0, Fp_mul(utoi(5), a4, p), Fp_mul(utoi(20), a6, p), Fp_mul(a42,subis(p,5), p), Fp_mul(Fp_mul(a4, a6, p), subis(p,4), p), Fp_sub(Fp_mul(Fp_sqr(a6, p), subis(p,8), p), Fp_mul(a4,a42, p), p)), utoi(4), p), h, p); if (n == 4) return gerepileupto(ltop, gel(f, 4)); gel(f2, 3) = FpXQ_sqr(gel(f, 3), h, p); gel(ff, 3) = gel(f, 3); gel(ff, 4) = FpX_Fp_mul(FpXQ_mul(rhs, gel(f, 4), h, p), gen_2, p); gel(f, 5) = FpX_sub(FpXQ_mul(gel(ff, 4), gel(f2, 2), h, p), FpXQ_mul(gel(ff, 3), gel(f2, 3), h, p), p); if (n == 5) return gerepileupto(ltop, gel(f, 5)); gel(f2, 4) = FpXQ_mul(rhs, FpXQ_sqr(gel(f, 4), h, p), h, p); gel(f2, 5) = FpXQ_sqr(gel(f, 5), h, p); gel(ff, 5) = FpXQ_mul(gel(f, 3), gel(f, 5), h, p); l = ((n/2) + 2)/2; for (m = 3; m <= l; m++) { gel(f, 2*m) = FpXQ_mul( FpX_sub(FpXQ_mul(gel(ff, m+2), gel(f2, m-1), h, p), FpXQ_mul(gel(ff, m), gel(f2, m+1), h, p), p), inv2y, h, p); gel(f2, 2*m) = FpXQ_mul(rhs, FpXQ_sqr(gel(f, 2*m), h, p), h, p); gel(ff, 2*m) = FpXQ_mul(rhs, FpXQ_mul(gel(f, 2*m), gel(f, 2*m-2), h, p), h, p); gel(f, 2*m+1) = FpX_sub(FpXQ_mul(gel(ff, m+2), gel(f2, m), h, p), FpXQ_mul(gel(ff, m+1), gel(f2, m+1), h, p), p); gel(f2, 2*m+1) = FpXQ_sqr(gel(f, 2*m+1), h, p); gel(ff, 2*m+1) = FpXQ_mul(gel(f, 2*m+1), gel(f, 2*m-1), h, p); } m = n/2; if (n&1L) res = FpX_sub(FpXQ_mul(gel(ff, m+2), gel(f2, m), h, p), FpXQ_mul(gel(ff, m+1), gel(f2, m+1), h, p), p); else res = FpXQ_mul( FpX_sub(FpXQ_mul(gel(ff, m+2), gel(f2, m-1), h, p), FpXQ_mul(gel(ff, m), gel(f2, m+1), h, p), p), inv2y, h, p); return gerepileupto(ltop, 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 p, long vx, long precS) { pari_sp ltop = avma; GEN c = find_coeff(a4, a6, 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 p, long precS) { pari_sp ltop = avma; GEN WEb = gmul(compute_W(Eba4, Eba6, p, varn(h), precS), gmodulsg(1,p)); GEN WEc = gmul(compute_W(Eca4, Eca6, p, varn(h), precS), gmodulsg(1,p)); GEN den = poleval(h, WEb); return gerepileupto(ltop, find_transformation(gmul(gsqr(den), WEc), WEb)); } /****************************************************************************/ /* SIMPLE ELLIPTIC CURVE OVER Fp */ /****************************************************************************/ static GEN a4a6_j(GEN a4, GEN a6, GEN p) { pari_sp ltop=avma; GEN a43 = Fp_mulu(Fp_powu(a4, 3, p), 4, p); GEN j = Fp_div(Fp_mulu(a43, 1728, p), Fp_add(a43, Fp_mulu(Fp_sqr(a6, p), 27, p), p), p); return gerepileupto(ltop, j); } /****************************************************************************/ /* EIGENVALUE */ /****************************************************************************/ struct eigen_ellinit { GEN a4; GEN h; GEN p; GEN RHS; GEN DRHS; GEN X12; GEN Gr; }; static void init_eigen(struct eigen_ellinit *Edat, GEN a4, GEN a6, GEN h, GEN p) { pari_sp ltop = avma; GEN RHS = FpX_rem(mkpoln(4, gen_1, gen_0, a4, a6), h, p); GEN DRHS = FpX_rem(mkpoln(3, utoi(3), gen_0, a4), h, p); GEN lambda = FpXQ_div(DRHS, FpX_Fp_mul(RHS, utoi(4), p), h, p); GEN C = FpX_sub(FpXQ_mul(lambda, DRHS, h, p), monomial(gen_2,1,0), p); GEN D = FpXQ_mul(FpX_Fp_mul(lambda, gen_2, p),FpX_sub(pol_x(0), C, p), h, p); GEN X12 = mkvec2(C, FpX_Fp_add(D, gen_m1, p)); GEN Gr = FpXQ_pow(RHS, shifti(p, -1), h, p); gerepileall(ltop, 4, &RHS, &DRHS, &X12, &Gr); Edat->a4 = icopy(a4); Edat->h = ZX_copy(h); Edat->p = icopy(p); Edat->RHS = RHS; Edat->DRHS = DRHS; Edat->X12 = X12; Edat->Gr = Gr; } static GEN eigen_elldbl(void *E, GEN P) { pari_sp ltop = avma; struct eigen_ellinit *Edat=(struct eigen_ellinit *)E; GEN p = Edat->p, h = Edat->h, x = gel(P,1), y = gel(P,2); if (ell_is_inf(P)) return gcopy(P); if (ZX_equal(x, pol_x(0)) && ZX_equal(y, pol_1(0))) return Edat->X12; else { GEN t1 = FpX_Fp_add(FpX_Fp_mul(FpXQ_sqr(x,h,p),utoi(3),p), Edat->a4, p); GEN t2 = FpXQ_mul(FpX_Fp_mul(y, gen_2, p), Edat->RHS, h, p); GEN lambda = FpXQ_div(t1, t2, h, p); GEN C = FpX_sub(FpXQ_mul(FpXQ_sqr(lambda, h, p), Edat->RHS, h, p), FpX_Fp_mul(x, gen_2, p), p); GEN D = FpX_sub(FpXQ_mul(lambda, FpX_sub(x, C, p), h, 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 eigen_elladd(void *E, GEN P, GEN Q) { pari_sp ltop = avma; struct eigen_ellinit *Edat=(struct eigen_ellinit *)E; GEN Px = gel(P,1), Py = gel(P,2); GEN Qx = gel(Q,1), Qy = gel(Q,2); GEN 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); if (ZX_equal(Px, Qx)) { if (ZX_equal(Py, Qy)) return eigen_elldbl(E, P); else return mkvec(gen_0); } lambda = FpXQ_div(FpX_sub(Py, Qy, p), FpX_sub(Px, Qx, p), h, p); C = FpX_sub(FpX_sub(FpXQ_mul(FpXQ_sqr(lambda, h, p), Edat->RHS, h, p), Px, p), Qx, p); D = FpX_sub(FpXQ_mul(lambda, FpX_sub(Px, C, p), h, p), Py, p); return gerepilecopy(ltop, mkvec2(C,D)); } static GEN eigen_ellpowu(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); 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 p, GEN tr) { pari_sp ltop = avma; GEN BP, Dr, nGr; ulong t; struct eigen_ellinit Edat; init_eigen(&Edat, a4, a6, h, p); nGr = FpX_neg(Edat.Gr, p); Dr = BP = mkvec2(pol_x(0), pol_1(0)); /*[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 (ZX_equal(gel(Dr,2), Edat.Gr)) { avma = ltop; return t; } if (ZX_equal(gel(Dr,2), nGr)) { avma = ltop; return ell-t; } Dr = gerepileupto(btop, eigen_elladd((void*)&Edat, Dr, BP)); } pari_err(bugparier,"find_eigen_value_power"); return 0; /* NOT REACHED */ } else { t = Fl_div(tr[1], 2, ell); if (t < (ell>>1)) t = ell - t; Dr = eigen_ellpowu(&Edat, BP, t); if (!ZX_equal(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 p) { pari_sp ltop = avma; pari_sp btop, st_lim; struct eigen_ellinit Edat; GEN P, BP, Dr, Gr, negGr; /*[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; init_eigen(&Edat, a4, a6, h, p); P = mkvec2(pol_x(0), pol_1(0)); BP = eigen_ellpowu(&Edat, P, ellk1); Dr = eigen_ellpowu(&Edat, P, lambda); Gr = Edat.Gr; negGr = FpX_neg(Edat.Gr, p); btop = avma; st_lim = stack_lim(btop, 1); for (t = 0; t < ellk; t += ellk1) { if (ZX_equal(gel(Dr,2), Gr)) { avma = ltop; return t+lambda; } if (ZX_equal(gel(Dr,2), negGr)) { avma = ltop; return ellk-(t+lambda); } Dr = eigen_elladd((void*)&Edat, Dr, BP); if (low_stack(st_lim, stack_lim(btop, 1))) Dr = gerepileupto(btop, Dr); } pari_err(bugparier,"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 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, p, dim); GEN Coefft = find_coeff(a4t, a6t, p, dim); GEN psi2 = mkpoln(4, utoi(4), gen_0, Fp_mulu(a4, 4, p), Fp_mulu(a6, 4, p)); GEN list = cgetg(dim+1, t_VEC); GEN Dpsi2 = mkpoln(3, utoi(6), gen_0, Fp_mulu(a4, 2, p)); gel(list, 1) = Dpsi2; for (k = 2; k <= dim; k++) { pari_sp btop = avma; GEN tsil = gel(list, k-1); GEN r = FpX_Fp_mul(Dpsi2, gel(tsil,3), p); for (j = 4; j < lg(tsil); j++) { long o = j - 2; GEN D = FpX_add(RgX_shift(Dpsi2, 1), FpX_Fp_mul(psi2, utoi(o-1), p), p); GEN E = FpX_Fp_mul(D, Fp_mulu(gel(tsil, j), o, p), p); r = FpX_add(r, RgX_shift(E, o-2), p); } gel(list, k) = gerepileupto(btop, r); } for (k = 2; k <= dim; k++) { GEN C = Fp_inv(shifti(mpfact(2*k),-1), p); gel(list, k) = FpX_Fp_mul(gel(list, k), C, p); } M = shallowtrans(RgXV_to_RgM(list, dim+2)); N = vecslice(M, 1, dim); V = FpC_sub(Coefft, Coeff, p); v = shallowconcat(FpM_gauss(N, V, p), mkcol2(gen_0, gen_0)); K = FpM_ker(M, p); if (lg(K) != 3) pari_err(talker, "trace not determined in a unique way"); K1 = FpC_Fp_mul(gel(K,1), Fp_inv(gcoeff(K,1,1), p), p); K2 = FpC_sub(gel(K,2), FpC_Fp_mul(K1, gcoeff(K,1,2), p), p); K2 = FpC_Fp_mul(K2, Fp_inv(gel(K2,2), p), p); K1 = FpC_sub(K1, FpC_Fp_mul(K2, gel(K1,2), p), p); v = FpC_add(v, FpC_Fp_mul(K1, Fp_sub(utoi(deg), gel(v,1), p), p), p); v = FpC_add(v, FpC_Fp_mul(K2, Fp_sub(pp1, gel(v,2), p), p), 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 = Fp_add(s, Fp_mul(gel(tlist, dim-i+1), gel(v, k-i+1), p), p); gel(tlist, dim-k+1) = gerepileuptoint(btop, Fp_div(s, stoi(-k), 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 p) { pari_sp ltop = avma; GEN dxxgj = FpX_eval(Dxxg, j, p); GEN dxJgj = FpX_eval(DxJg, j, p); GEN dJJgj = FpX_eval(DJJg, j, p); GEN E42 = Fp_sqr(E4, p), E6ovE4 = Fp_div(E6, E4, p); GEN a = Fp_mul(gprime, dxxgj, p); GEN b = Fp_mul(Fp_mul(Fp_mulu(j,2*q, p), dxJgj, p), E6ovE4, p); GEN c = Fp_mul(Fp_div(Fp_sqr(E6ovE4, p), gprime, p), j, p); GEN d = Fp_mul(Fp_mul(c,sqru(q), p), Fp_add(pJ, Fp_mul(j, dJJgj, p), p), p); GEN e = Fp_sub(Fp_div(E6ovE4,utoi(3), p), Fp_div(E42, Fp_mulu(E6,2,p), p), p); GEN f = Fp_sub(Fp_sub(b,a,p), d, p); return gerepileuptoint(ltop, Fp_add(Fp_div(f,px,p), Fp_mulu(e,q,p), 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 p) { pari_sp ltop = avma, btop; GEN Roots, gprime, u1; long k, vx = 0, vJ = MAXVARN; GEN E4 = Fp_div(a4, stoi(-3), p); GEN E6 = Fp_mul(a6, shifti(p, -1), p); GEN E42 = Fp_sqr(E4, p); GEN E43 = Fp_mul(E4, E42, p); GEN E62 = Fp_sqr(E6, p); GEN delta = Fp_div(Fp_sub(E43, E62, p), utoi(1728), p); GEN j = Fp_div(E43, delta, p); GEN Dx = deriv(meqn, vx); GEN DJ = deriv(meqn, vJ); GEN Dxg = FpXY_evaly(Dx, g, p, vJ); GEN px = FpX_eval(Dxg, j, p), dx = Fp_mul(px, g, p); GEN DJg = FpXY_evaly(DJ, g, p, vJ); GEN pJ = FpX_eval(DJg, j, p), dJ = Fp_mul(pJ, j, p); GEN Dxx = deriv(Dx, vx); GEN DxJg = FpX_deriv(Dxg, p); GEN Dxxg = FpXY_evaly(Dxx, g, p, vJ); GEN DJJg = FpX_deriv(DJg, p); GEN a = Fp_mul(dJ, Fp_mul(g, E6, p), p); GEN b = Fp_mul(E4, dx, 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 = Fp_div(a, b, p); u1 = compute_u(gprime, Dxxg, DxJg, DJJg, j, pJ, px, 1, E4, E6, p); Roots = FpX_roots(FpXY_evaly(meqn, g, p, vJ), p); btop = avma; for (k = lg(Roots)-1; k >= 1; k--, avma = btop) { GEN jt = gel(Roots, k); GEN pxstar = FpX_eval(Dxg, jt, p); GEN dxstar = Fp_mul(pxstar, g, p); GEN pJstar = FpX_eval(DJg, jt, p); GEN dJstar = Fp_mul(Fp_mulu(jt, ell, p), pJstar, p); GEN u = Fp_mul(Fp_mul(dxstar, dJ, p), E6, p); GEN v = Fp_mul(Fp_mul(dJstar, dx, p), E4, p); GEN E4t = Fp_div(Fp_mul(Fp_sqr(u, p), jt, p), Fp_mul(Fp_sqr(v, p), Fp_sub(jt, utoi(1728), p), p), p); GEN E6t = Fp_div(Fp_mul(u, E4t, p), v, p); GEN u2 = compute_u(gprime, Dxxg, DxJg, DJJg, jt, pJstar, pxstar, ell, E4t, E6t, p); GEN pp1 = Fp_mulu(Fp_sub(u1, u2, p), 3*ell, p); GEN a4t = Fp_mul(mulsi(-3, powuu(ell,4)), E4t, p); GEN a6t = Fp_mul(mulsi(-2, powuu(ell,6)), E6t, p); GEN h = find_kernel(a4, a6, ell, a4t, a6t, pp1, p); if (h) return gerepilecopy(ltop, mkvec3(a4t, a6t, h)); } pari_err(bugparier, "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 p) { pari_sp ltop = avma; long vx = 0, vJ = MAXVARN; GEN h; GEN E4 = Fp_div(a4, stoi(-3), p); GEN E6 = Fp_mul(a6, shifti(p, -1), p); GEN E42 = Fp_sqr(E4, p); GEN E43 = Fp_mul(E4, E42, p); GEN E62 = Fp_sqr(E6, p); GEN delta = Fp_div(Fp_sub(E43, E62, p), utoi(1728), p); GEN j = Fp_div(E43, delta, p); GEN Dx = deriv(meqn, vx); GEN DJ = deriv(meqn, vJ); GEN Dxg = FpXY_evaly(Dx, g, p, vJ); GEN px = FpX_eval(Dxg, j, p), dx = Fp_mul(px, g, p); GEN DJg = FpXY_evaly(DJ, g, p, vJ); GEN pJ = FpX_eval(DJg, j, p), dJ = Fp_mul(j, pJ, p); GEN Dxx = deriv(Dx, vx); GEN DxJg = FpX_deriv(Dxg, p); GEN ExJ = FpX_eval(DxJg, j, p); ulong tis = ugcd(12, ell-1), is = 12 / tis; GEN itis = Fp_inv(stoi(-tis), p); GEN deltal = Fp_div(Fp_mul(delta, Fp_powu(g, tis, p), p), powuu(ell, 12), 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", p); E4l = Fp_div(E4, sqru(ell), p); jl = Fp_div(Fp_powu(E4l, 3, p), deltal, p); E6l = Fp_sqrt(Fp_mul(Fp_sub(jl, utoi(1728), p), deltal, p), p); p_1 = gen_0; } else { GEN jl, f, fd, Dgs, Djs, jld; GEN E2s = Fp_div(Fp_mul(Fp_neg(Fp_mulu(E6, 12, p), p), dJ, p), Fp_mul(Fp_mulu(E4, is, p), dx, p), p); GEN gd = Fp_mul(Fp_mul(E2s, itis, p), g, p); GEN jd = Fp_div(Fp_mul(Fp_neg(E42, p), E6, p), delta, p); GEN E0b = Fp_div(E6, Fp_mul(E4, E2s, p), p); GEN Dxxgj = FpXY_eval(Dxx, g, j, p); GEN Dgd = Fp_add(Fp_mul(gd, px, p), Fp_mul(g, Fp_add(Fp_mul(gd, Dxxgj, p), Fp_mul(jd, ExJ, p), p), p), p); GEN DJgJj = FpX_eval(FpX_deriv(DJg, p), j, p); GEN Djd = Fp_add(Fp_mul(jd, pJ, p), Fp_mul(j, Fp_add(Fp_mul(jd, DJgJj, p), Fp_mul(gd, ExJ, p), p), p), p); GEN E0bd = Fp_div(Fp_sub(Fp_mul(Dgd, itis, p), Fp_mul(E0b, Djd, p), p), dJ, p); E4l = Fp_div(Fp_sub(E4, Fp_mul(E2s, Fp_sub(Fp_sub(Fp_add(Fp_div(Fp_mulu(E0bd, 12, p), E0b, p), Fp_div(Fp_mulu(E42, 6, p), E6, p), p), Fp_div(Fp_mulu(E6, 4, p), E4, p), p), E2s, p), p), p), sqru(ell), p); jl = Fp_div(Fp_powu(E4l, 3, p), deltal, p); f = Fp_div(powuu(ell, is), g, p); fd = Fp_neg(Fp_mul(Fp_mul(E2s, f, p), itis, p), p); Dgs = FpXY_eval(Dx, f, jl, p); Djs = FpXY_eval(DJ, f, jl, p); jld = Fp_div(Fp_mul(Fp_neg(fd, p), Dgs, p), Fp_mulu(Djs, ell, p), p); E6l = Fp_div(Fp_mul(Fp_neg(E4l, p), jld, p), jl, p); p_1 = Fp_mul(Fp_mulu(E2s, ell, p), shifti(p, -1), p); } a4tilde = Fp_mul(Fp_mul(stoi(-3), powuu(ell,4), p), E4l, p); a6tilde = Fp_mul(Fp_mul(stoi(-2), powuu(ell,6), p), E6l, p); h = find_kernel(a4, a6, ell, a4tilde, a6tilde, p_1, p); return gerepilecopy(ltop, mkvec3(a4tilde, a6tilde, h)); } static GEN find_isogenous(GEN a4, GEN a6, long ell, struct meqn *MEQN, GEN g, GEN p) { return (MEQN->type == 'C') ? find_isogenous_from_canonical(a4, a6, ell, MEQN->eq, g, p) : find_isogenous_from_Atkin(a4, a6, ell, MEQN->eq, g, p); } static GEN find_kernel_power(GEN Eba4, GEN Eba6, GEN Eca4, GEN Eca6, ulong ell, struct meqn *MEQN, GEN kpoly, GEN Ib, GEN p) { pari_sp ltop = avma, btop; GEN a4t, a6t, gtmp; GEN num_iso = find_numerator_isogeny(Eba4, Eba6, Eca4, Eca6, kpoly, p, ell+1); GEN mpoly = FpXY_evalx(MEQN->eq, a4a6_j(Eca4, Eca6, p), p); GEN tmp, mroots = FpX_roots(mpoly, 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), 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 = FpX_sqr(kpoly, p); h = lift(numer(gsubst(gtmp, vx, gdiv(num_iso, kpoly2)))); if (signe(a4a6_divpolmod(Eba4, Eba6, ell, h, p))) { GEN Ic = gdiv(gsubst(num_iso, vx, Ib), gsqr(gsubst(kpoly, vx, Ib))); GEN kpoly_new = lift(numer(gsubst(gtmp, vx, Ic))); return gerepilecopy(ltop, mkvecn(5, a4t, a6t, kpoly_new, gtmp, Ic)); } avma = btop; } pari_err(talker, "failed to find kernel polynomial"); return NULL; /*NOT REACHED*/ } /****************************************************************************/ /* TRACE */ /****************************************************************************/ enum mod_type {MTpathological, MTAtkin, MTElkies, MTone_root, MTroots}; /* Berlekamp variant */ static GEN study_modular_eqn(long ell, GEN mpoly, GEN p, enum mod_type *mt, long *ptr_r) { pari_sp ltop = avma; long r = 0; GEN g = gen_0; if (degpol(FpX_gcd(mpoly, FpX_deriv(mpoly,p), p)) > 0) *mt = MTpathological; else { GEN XP = FpXQ_pow(pol_x(0), p, mpoly, p); GEN G = FpX_gcd(ZX_sub(XP, pol_x(0)), mpoly, p); long dG = degpol(G); if (!dG) { GEN L = FpXQ_matrix_pow(XP, ell+1, ell+1, mpoly, p); long s = ell + 1 - FpM_rank(RgM_Rg_add(L, gen_m1), p); r = (ell + 1)/s; *mt = MTAtkin; } else { g = FpX_oneroot(G, p); switch(dG) { case 1: *mt = MTone_root; break; case 2: *mt = MTElkies; break; default: *mt = (dG == ell + 1)? MTroots: MTpathological; } } } *ptr_r = r; 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 gerepilecopy(ltop, g); } /*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 p, ulong smallfact, pari_timer *T) { pari_sp ltop = avma, btop, st_lim; GEN tmp, Eba4, Eba6, Eca4, Eca6, Ib, kpoly; ulong lambda, ellk = upowuu(ell, k), pellk = umodiu(p, ellk); long cnt; if (DEBUGLEVEL) { err_printf("Trace mod %ld", ell); } Eba4 = a4; Eba6 = a6; tmp = find_isogenous(a4,a6, ell, MEQN, g, 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, p, tr); if (DEBUGLEVEL>1) err_printf(" [%ld ms]", timer_delay(T)); 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, p); if (!tmp) { avma = ltop; return NULL; } lambda = find_eigen_value_power(a4, a6, ell, cnt, gel(tmp,3), lambda, 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(T)); } 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 p) { pari_sp ltop = avma; long nval = 0; ulong teta, pell = umodiu(p, ell), invp = Fl_inv(pell, ell); GEN val_pos = cgetg(1+ell, t_VECSMALL), P = gel(factoru(r), 1); GEN T = 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; T[3] = Fl_neg(teta, ell); U[3] = Fl_mul(invp, teta, ell); a = Flxq_pow(U, utoi(r/P[1]), T, ell); if (!Flx_equal1(a) && Flx_equal1(Flxq_pow(a, utoi(P[1]), T, ell))) { pari_sp av = avma; long i, l=lg(P); for (i = 2; i < l; i++, avma = av) if (Flx_equal1(Flxq_pow(U, utoi(r/P[i]), T, 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 p) { ulong a = Fl_mul(Fl_sqrt(umodiu(p,ell), ell), 2, ell); return mkvecsmall2(a, ell - a); } static GEN find_trace_lp1_roots(long ell, GEN p) { ulong ell2 = ell * ell, pell = umodiu(p, 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 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 T; if (ell <= 13) { long lp = bit_accuracy(lg(p))-bfffo(*int_MSW(p)); 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)) return gen_0; if (DEBUGLEVEL) { err_printf("Process prime %5ld. ", ell); timer_start(&T); } meqnj = FpXY_evalx(MEQN.eq, a4a6_j(a4, a6, p), p); g = study_modular_eqn(ell, meqnj, 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, p); 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, p, smallfact, &T); 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, p, smallfact, &T); if (!tr) { avma = ltop; return NULL; } break; case MTroots: tr = find_trace_lp1_roots(ell, p); kt = 2; break; case MTAtkin: tr = find_trace_Atkin(ell, r, p); if (lg(tr)==1) pari_err(talker,"not a prime number"); 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(&T)); } 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, GEN a4, GEN p) { GEN diff = compute_diff(V); GEN pre = cgetg(lg(diff), t_VEC); long i, l = lg(diff); gel(pre, 1) = FpE_mul(P, gel(diff, 1), a4, p); /* 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 = FpE_add(gel(pre, i-1), FpE_mul(P, d, a4, p), a4, p); 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 a4, GEN a6, GEN p) { pari_sp av1, av2; GEN baby, giant, SgMb, Mb, Mg, den, Sg, dec_inf, div, pp1 = addis(p,1); GEN P, Pb, Pg, point, diff, pre, table, table_ind; long best_i, i, lbaby, lgiant, lp = lg(p), k = lg(compile_atkin)-1; 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 choose_card(card, a4, a6, p); } 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 = random_FpE(a4, a6, p); point = FpE_mul(P, Mu, a4, p); Pb = FpE_mul(point, Mg, a4, p); Pg = FpE_mul(point, Mb, a4, p); /* Precomputation for babies */ pre = BSGS_pre(&diff, baby, Pb, a4, p); /*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_VEC); for (i = 1; i < lbaby; i++) gel(table,i) = cgeti(lp); av1 = avma; /* (p+1 - u - Mu*Mb*Sg) P - (baby[1]) Pb */ point = FpE_mul(P, subii(subii(pp1, u), mulii(Mu, addii(SgMb, mulii(Mg, gel(baby,1))))), a4, p); affii(gel(point,1), gel(table, 1)); for (i = 2; i < lbaby; i++) { GEN d = subii(gel(baby, i), gel(baby, i-1)); point = FpE_sub(point, gel(pre, ZV_search(diff, d)), a4, p); affii(gel(point,1), gel(table, i)); point = gerepilecopy(av1, point); } /* Precomputations for giants */ pre = BSGS_pre(&diff, giant, Pg, a4, p); /* Look for a collision among the x-coordinates */ gen_sort_inplace(table, (void*)&cmpii, &cmp_nodata, &table_ind); av1 = avma; point = FpE_mul(Pg, gel(giant, 1), a4, p); for (i = 1; i < lgiant; i++) { GEN d; long s = ZV_search(table, gel(point, 1)); if (s) { GEN B = gel(baby,table_ind[s]), G = gel(giant,i); GEN GMb = mulii(G, Mb), BMg = mulii(B, Mg); /* p+1 - u - Mu (Sg Mb + GIANT Mb + BABY Mg) */ GEN card = subii(subii(pp1, u), mulii(Mu, addii(SgMb, addii(GMb, BMg)))); card = mkvec2(card, addii(card, mulii(mulsi(2,Mu), GMb))); return choose_card(card, a4, a6, p); } d = subii(gel(giant, i+1), gel(giant, i)); point = FpE_add(point, gel(pre, ZV_search(diff, d)), a4, p); if ((i & 0xff) == 0) point = gerepilecopy(av1, point); } /* no match ? */ pari_err(bugparier,"match_and_sort"); return NULL; /* not reached */ } /* 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 ellsea(GEN E, GEN p, long smallfact) { const long MAX_ATKIN = 21; pari_sp ltop = avma, btop, st_lim; long i, nb_atkin, lp, M; GEN res, cat; GEN compile_atkin, tr, bound, bound_bsgs, champ; GEN prod_atkin = gen_1, max_traces = gen_0; 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); double bound_gr = 1.; const double growth_factor = 1.26; long ell = 2; byteptr primepointer = diffptr + 1; if (!modular_eqn && !get_seadata(0)) return NULL; /*First compute the trace modulo 2 */ switch(FpX_nbroots(mkpoln(4, gen_1, gen_0, a4, a6), p)) { case 3: /* bonus time: 4 | #E(Fp) = p+1 - a_p */ i = mod4(p)+1; if (i == 4) i = 0; tr = mkintmodu(i, 4); break; case 1: tr = mkintmod(gen_0, gen_2); break; default : /* 0 */ tr = mkintmod(gen_1, gen_2); break; } if (smallfact==1 && gel(tr,2) != gen_1) { if (DEBUGLEVEL) err_printf("Aborting: #E(Fp) 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 tr. */ bound = sqrti(shifti(p, 4)); M = 1000000; lp = bit_accuracy(lg(p)) - bfffo(*int_MSW(p)); if (lp <= 160) bound_bsgs = mulru(divru(powru(dbltor(1.048), lp), 9), M); else if (lp <= 192) bound_bsgs = mulru(divrr(powru(dbltor(1.052), lp), dbltor(16.65)), M); else if (lp <= 306) bound_bsgs = mulru(mulrr(powru(dbltor(1.035), lp), dbltor(1.35)), M); else bound_bsgs = mulru(mulrr(powru(dbltor(1.035), 307), dbltor(1.35)), M); compile_atkin = zerovec(MAX_ATKIN); nb_atkin = 0; btop = avma; st_lim = stack_lim(btop, 1); while (1) { long kt = 1; GEN ellkt, trace_mod; NEXT_PRIME_VIADIFF(ell, primepointer); trace_mod = find_trace(a4, a6, ell, p, &kt, smallfact); if (trace_mod==gen_0) pari_err(talker,"not enough modular polynomials"); if (!trace_mod) continue; ellkt = powuu(ell, kt); if (lg(trace_mod) == 2) { if (smallfact && ell>smallfact && dvdiu(addis(p, 1 - trace_mod[1]), ell)) { if (DEBUGLEVEL) err_printf("\nAborting: #E(Fp) divisible by %ld\n",ell); avma = ltop; return gen_0; } tr = crt(ellkt, stoi(trace_mod[1]), tr); } else { add_atkin(compile_atkin, mkvec2(ellkt, trace_mod), &nb_atkin); prod_atkin = value(-1, compile_atkin, nb_atkin); } if (cmpii(mulii(gel(tr, 1), prod_atkin), bound) > 0) { GEN bound_tr; if (!nb_atkin) return gerepileuptoint(ltop, centerlift(tr)); bound_tr = mulrr(bound_bsgs, dbltor(bound_gr)); bound_gr *= growth_factor; if (signe(max_traces)) { max_traces = truedivii(mulis(max_traces,2*(lg(trace_mod)-1)), 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, gel(tr, 1)); champ = champion(compile_atkin, nb_atkin, bound_atkin); max_traces = gel(champ,2); if (cmpir(max_traces, bound_tr) < 0) break; if (DEBUGLEVEL>=2) err_printf("%Ps remaining possibilities.\n", max_traces); } } if (low_stack(st_lim, stack_lim(btop, 1))) gerepileall(btop, 4, &tr, &compile_atkin, &max_traces, &prod_atkin); } cat = shallowextract(compile_atkin, gel(champ, 1)); if (DEBUGLEVEL) err_printf("Match and sort for %Ps possibilities.\n",gel(champ, 2)); res = match_and_sort(cat, gel(tr,1), gel(tr,2), a4,a6,p); return gerepileuptoint(ltop, subii(addis(p, 1), res)); } pari-2.5.5/src/modules/elldata.c0000644000175000017500000001416012147140047015117 0ustar billbill/* $Id$ 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(talker,"Incorrect curve name in ellconvertname"); if (f<0 || c<0 || i<0) pari_err(talker,"Incomplete curve name in ellconvertname"); return mkvec3s(f,c,i); } case t_VEC: if (lg(n)!=4) pari_err(talker,"Incorrect vector in ellconvertname"); else { 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(typeer,"ellconvertname"); return gerepilecopy(av, shallowconcat1(mkvec3(f, ellrecode(itos(c)), s))); } } pari_err(typeer,"ellconvertname"); return NULL; /*Not reached*/ } static GEN ellcondfile(long f) { pari_sp av = avma; long n = f / 1000; char *s = stackmalloc(strlen(pari_datadir) + 12 + 20 + 1); pariFILE *F; GEN V; sprintf(s, "%s/elldata/ell%ld", pari_datadir, n); F = pari_fopengz(s); avma = av; if (!F) pari_err(talker,"Missing elldata for conductor %ld\n[need %s]",f,s); V = gp_read_stream(F->file); if (!V || typ(V)!=t_VEC ) pari_err(talker,"Incompatible elldata file %s\n",s); pari_fclose(F); return V; } /* FIXME: could use a binary search */ static GEN ellcondlist(long f) { GEN v, V = ellcondfile(f); long i; for (i=1; i= 0) { if (cmp) break; v = gel(V,i); return vecslice(v,2, lg(v)-1); } } return cgetg(1,t_VEC); } static GEN ellsearchbyname(GEN V, char *name) { long j; for (j=1; j= 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(talker,"Incorrect curve name in ellsearch"); if (f<0 || c<0 || i<0) pari_err(talker,"Incomplete curve name in ellsearch"); return gerepilecopy(ltop, ellsearchbyname(ellcondlist(f), GSTR(name))); } GEN ellidentify(GEN E) { pari_sp ltop=avma; GEN V, M, G = ellglobalred(E); long j; V = ellcondlist(itos(gel(G,1))); M = ellchangecurve(vecslice(E,1,5),gel(G,2)); for (j=1; jb) break; for(k=2; k 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(talker, "No division in GetSharp"); 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(talker, "Degrees do not match 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_pow(pol_x(data->v), stoi(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++) { nb = IsIsomorphic(data, &fdata, gel(vpl, j)); if (nb) pari_err(talker, "Oops, fields are isomorphic in TamelyRamifiedCase!\n"); } 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(talker,"Number of fields incorrect in TamelyRamifiedCase\n"); #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; nbpol = gen_1; for (i = 0; i < data->e; i++) { long v_start, zero = 0; GEN nbcf; if (i == 0) { v_start = 1; nbcf = mulii(data->qm1, powiu(data->q, data->c - 1)); } else { GEN 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(talker,"too many extensions in padicfields"); 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) { /* The best thing seems to be to jump randomly among the polynomials... */ 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(talker, "incorrect discriminant in WildlyRamifiedCase\n"); } #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 *data) { GEN T, z; /* v - primroot(p) */ if (data->f == 1) return deg1pol_shallow(gen_1, Fp_neg(pgener_Fp(data->p), data->pr), data->v); T = init_Fq(data->p, data->f, data->v); z = gener_FpXQ(T, data->p, NULL); z = ZpXQ_sqrtnlift(gen_1, data->qm1, z, T, data->p, data->r); return FpX_red(ZXQ_charpoly(z, T, data->v), data->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 v, long flag) { long e = efj[1], f = efj[2], j = efj[3]; GEN 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) { GEN npol = powiu(data.q, e+1); if (lgefint(data.p) == 3 && expi(npol) < 19) { long i, l = itou(npol); data.roottable = cgetg(l+1, t_VEC); for (i = 1; i <= l; i++) gel(data.roottable, i) = NULL; } data.pk = get_pk(&data); pols = WildlyRamifiedCase(&data); } else pols = TamelyRamifiedCase(&data); if (flag == 1) { long i, l; GEN p1 = cgetg_copy(pols, &l); for (i = 1; i < l; i++) gel(p1, i) = mkvec5(gcopy(gmael2(pols, i, 1)), utoipos(e), utoipos(f), utoi(f*(e+j-1)), gcopy(gmael2(pols, i, 2))); pols = gerepileupto(av, p1); } else { long i, l; GEN p1 = cgetg_copy(pols, &l); for (i = 1; i < l; i++) gel(p1, i) = gcopy(gmael2(pols, i, 1)); pols = gerepilecopy(av, p1); } return 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(talker,"too many ramification possibilities in padicfields"); } 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, v = fetch_user_var("y"); 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), v, 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(arither1); /* be nice to silly users */ if (!BPSW_psp(p)) pari_err(talker,"p must be a prime in padicfields"); switch(typ(N)) { case t_VEC: if (lg(N) != 3 || typ(gel(N,2)) != t_INT) pari_err(typeer, "padicfields"); d = itos(gel(N,2)); N = gel(N,1); /* fall through */ case t_INT: m = itos(N); if (m <= 0) pari_err(talker,"non-positive degree in padicfields()"); break; } 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.5.5/src/modules/mpqs.h0000644000175000017500000005371112147140047014503 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; 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.5.5/src/modules/kummer.c0000644000175000017500000011104212147140047015006 0ustar billbill/* $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. */ /*******************************************************************/ /* */ /* 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_cmp0(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 = T2_from_embed_norm(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 = T2_from_embed_norm(v,r1); if (gcmp(t,nmax) < 0) { B=v; nmax=t; besti=i; bestk = k; continue; } v = vecmul(b, gel(zk,i+ru)); t = T2_from_embed_norm(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 = (prec-1)<<1; 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 pr1, GEN pr2, tau_s *tau) { GEN p = gel(pr1,1); GEN x = gel(pr1,2); GEN b1= gel(pr1,5); GEN b2= gel(pr2,5); if (!equalii(p, gel(pr2,1)) || pr_get_e(pr1) != pr_get_e(pr2) || pr_get_f(pr1) != pr_get_f(pr2)) return 0; if (ZV_equal(x,gel(pr2,2))) return 1; for(;;) { if (int_elt_val(nfz,x,p,b2,NULL)) return 1; x = FpC_red(tauofelt(x, tau), p); if (int_elt_val(nfz,x,p,b1,NULL)) 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, RgX_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(talker,"bug%d in kummer",i); return cgetg(1,t_VEC); } static GEN get_gell(GEN bnr, GEN subgp, long all) { GEN gell; if (all && all != -1) gell = stoi(all); else if (subgp) gell = det(subgp); else gell = det(diagonal_shallow(bnr_get_cyc(bnr))); if (typ(gell) != t_INT) pari_err(arither1); 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 (lg(gel(Msup,1)) != 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 + nbits2nlong(((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++) z[i] = 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++) { 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 */ 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(talker,"main variable in kummer must not be x"); /* 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<-1?-all:all); ell = itos(gell); if (ell == 1) return pol_x(0); if (!uisprime(ell)) pari_err(impl,"kummer for composite relative degree"); 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, prec); 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 */ 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; } 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.5.5/src/modules/part.c0000644000175000017500000002022312147140047014454 0ustar billbill/* $Id$ 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) = local(a, b, c); 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,0,cos((g(h,q)-2*h*n)*Pi/q)))) * g(h, q) = if(q<3,0,sum(k=1,q-1,k*(frac(h*k/q)-1/2))) * 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) = local(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, 0, sum(k=1,q-1,k*(frac(h*k/q)-1/2))) */ /* assume h < q and (h,q) = 1. Not memory clean. */ static GEN g(ulong q, ulong h) { ulong k, kh; GEN i2; if (q < 3) return gen_0; if (h == 1) return gdivgs(muluu(q-1,q-2), 12); if (h == 2) return q == 3? mkfrac(gen_m1, utoipos(6)) : gdivgs(muluu((q-1)>>1,(q-5)>>1), 6); k = q % h; if (k <= 2) { GEN h2 = sqru(h); return k == 1? gdivgs(mului((q-1)/h, subsi(q-1, h2)), 12) : gdivgs(mului((q-2)/h, subsi((q<<1)-1, h2)), 24); /* k=2 */ } /* TODO: expr for h-1 mod h + gcd-style computation */ kh = h; if (ULONG_MAX/h > q) { long l3 = 0; for (k = 1; k < q; k++) { l3 += k * ((kh << 1) - q); kh += h; if (kh >= q) kh -= q; } i2 = stoi(l3); } else { pari_sp av = avma; i2 = gen_0; for (k = 1; k < q; k++) { i2 = addii(i2, mulss(k, (kh << 1) - q)); if ((k & 31) == 0) i2 = gerepileuptoint(av, i2); kh += h; if (kh >= q) kh -= q; } } return gdivgs(i2, q<<1); } /* L(n, q) = if(q==1,1,sum(h=1,q-1,if(gcd(h,q)>1,0,cos((g(h,q)-2*h*n)*Pi/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), hn; GEN r, res = stor(0, pr), pi_q = divru(mppi(pr), q); pari_sp av = avma; for (h = 1, hn = 0; h < q; h++, avma = av) { GEN t; hn += nmodq; if (hn >= q) hn -= q; if (ugcd(q, h) > 1) continue; r = gsubgs(g(q,h), hn << 1); t = isintzero(r)? addrs(res, 1): addrr(res, mpcos(gmul(pi_q,r))); affrr(t, res); } return res; } /* 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(typeer, "partition function"); if (signe(n) < 0) return gen_0; if (cmpiu(n, 2) < 0) return gen_1; if (cmpii(n, uu32toi(0x38d7e, 0xa4c68000)) >= 0) pari_err(talker, "arg to partition function must be < 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 */ 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))); } /** * Return a vector in which each element is a vector of partitions of * the positive integer n, in which the length of each of these partitions * is pext, in which the minimum element in each of the partitions is amin, * and in which the maximum element in each of the partitions is amax. * R. J. Mathar, mathar@strw.leidenuniv.nl, 2008-05-05 */ /* assume pext >= 2 */ static GEN partitr(long n, long pext, long amin, long amax) { GEN pi; if (pext == 2) { long a, L1 = maxss(amin, n-amax), L2 = minss(amax, n/pext); if (L1 > L2) return NULL; pi = cgetg(L2 - L1 + 2, t_VEC); for (a = L1; a <= L2; a++) gel(pi, a-L1+1) = mkvecsmall2(a, n-a); } else { pari_sp av = avma; long a, l, L1 = amin, L2 = minss(amax, n/pext); if (L1 > L2) return NULL; pi = cgetg(L2 - L1 + 2, t_VEC); l = 1; for (a = L1; a <= L2; a++) { GEN P = partitr(n-a, pext-1, a, amax); long i, lP; if (!P) continue; lP = lg(P); for (i = 1; i < lP; i++) gel(P,i) = vecsmall_prepend(gel(P,i), a); gel(pi, l++) = P; } if (l == 1) { avma = av; return NULL; } setlg(pi, l); pi = gerepilecopy(av, shallowconcat1(pi)); } return pi; } /** * Return a vector in which each element is a vector of partitions of * the positive integer n, * and in which the maximum element in each of the partitions is amax. * The restrictions on the maximum element can be lifted setting amax to zero, * which allows for each element to grow to its maximum of n itself. * * Example: partit(9,2) yields * [[1, 2, 2, 2, 2], [1, 1, 1, 2, 2, 2], [1, 1, 1, 1, 1, 2, 2], * [1, 1, 1, 1, 1, 1, 1, 2], [1, 1, 1, 1, 1, 1, 1, 1, 1]] * R. J. Mathar, mathar@strw.leidenuniv.nl, 2008-05-05 */ GEN partitions(long n, long amax) { pari_sp av = avma; GEN pi; long p, l; /* lift the restriction on the maximum element if amax=0 */ if (amax == 0) amax = n; if (amax < 0) return cgetg(1, t_VEC); if (n <= 0) { if (n < 0) return cgetg(1, t_VEC); pi = cgetg(2, t_VEC); gel(pi,1) = cgetg(1, t_VECSMALL); return pi; } /* the partitions are generated in Abramowitz-Stegun order: * first the partitions with 1 element, then those with 2, then * those with 3 until 1+1+1+..+1=n, the longest, is created. p is the * length of these partitions. */ /* partitions with 1 element */ pi = cgetg(n+1, t_VEC); l = 1; if (n <= amax) gel(pi, l++) = mkvec( mkvecsmall(n) ); /* vector of partitions of length p, elements in the range of 1.. amax */ for (p = 2; p <= n; ++p) { GEN P = partitr(n, p, 1, amax); if (P) gel(pi, l++) = P; } setlg(pi, l); return gerepilecopy(av, shallowconcat1(pi)) ; } pari-2.5.5/src/modules/groupid.c0000644000175000017500000005030212147140047015160 0ustar billbill/* $Id$ 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; pari_err(talker,"Not a group in group_ident"); } 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; } } pari_err(talker,"Not a group in group_ident"); } 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; } pari_err(talker,"Not a group in group_ident"); } 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; } pari_err(talker,"Not a group in group_ident"); } while (*t!=-1) t++; } } } return 0; } long group_ident(GEN G, GEN S) { pari_sp av = avma; long idx = group_ident_i(G, S); avma = av; if (!idx) pari_err(impl,"galoisidentify for groups of order >127"); 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; if (n > 30) pari_err(talker, "Classification of transitive groups of order > 30 is not known"); 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.5.5/src/test/0000755000175000017500000000000012212611624012647 5ustar billbillpari-2.5.5/src/test/dotest0000755000175000017500000001000012147140047014071 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 wrln () { echo "$1"; echo "$1" >> $file_bench; } wr () { echo $n "$1$c"; echo $n "$1$c" >> $file_bench; } 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 file_bench=Bench-$VersionMajor.$VersionMinor.$patch if (touch $file_bench 2> /dev/null); then SUF= else if test ! $x $execdir/gp.exe; then echo "build gp.exe first" >&2; exit 1 fi if (echo | $RUNTEST gp --test -q 2> /dev/null); then gp=gp else gp="command /c gp" fi if (expr 2 \* 2 2> /dev/null); then exprbug=0; else exprbug=1; fi SUF="exe"; file_bench=Bench.$patch fi $RM -f $file_bench dotestSUF=${dotestSUF:-"sta dyn"} for arg in $dotestSUF; do case "$arg" in sta|dyn) if test $x $execdir/gp-$arg; then SUF="$SUF $arg"; fi ;; esac 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 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} wr "* Testing $testname $c" for suf in $SUF; do wr " for gp-$suf..$c" case "$suf" in exe) file_diff=$testname.dif;; *) file_diff=$testname-$suf.dif gp=$execdir/gp-$suf;; esac (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 if test -z "$pat"; then wr "TIME=$time"; else eval BUG$suf=BUG eval files$suf=\"'$'files$suf $file_diff\" wr "BUG [${time:-0}]" fi done wrln 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 -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 "12[8-9],137"` case "$pat" in *128,137*) elen=30;; *129,137*) elen=25;; *) elen=0;; esac sys0190=`grep "^+ SYS0190\>" $file_diff` if test -n "$sys0190"; then len=`expr $len - 2` # more verbose error message on OS/2 fi 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.5.5/src/test/kerntest.c0000644000175000017500000000353111636712103014657 0ustar billbill#include "pari.h" GEN gen_0, gen_1, gen_m1, gen_2, gen_m2; pari_sp top, bot, avma; size_t memused = 0; ulong DEBUGLEVEL,DEBUGMEM = 0; const double LOG10_2 = 0.; const long lontyp[] = {0}; VOLATILE int PARI_SIGINT_block, PARI_SIGINT_pending; 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.5.5/src/test/dummy.c0000644000175000017500000000047712147140047014161 0ustar billbillvoid 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_warn(){} void quadratic_prec_mask(){} pari-2.5.5/src/test/32/0000755000175000017500000000000012212611624013073 5ustar billbillpari-2.5.5/src/test/32/idealramgroups0000644000175000017500000000045311636712103016041 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 ])]]] Total time spent: 3684 pari-2.5.5/src/test/32/nfields0000644000175000017500000014634112147140047014456 0ustar billbill echo = 1 (on) ? gettime;p2=Pol([1,3021,-786303,-6826636057,-546603588746,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] ? setrand(1);a=matrix(3,5,j,k,vectorv(5,l,random\10^8)); ? setrand(1);as=matrix(3,3,j,k,vectorv(5,l,random\10^8)); ? 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.072312766896812300380582649294307897075 + 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]]], [-2.428 5174907194186068992069565359418365, 1.9647119211288133163138753392090569931 + 0.80971492418897895128294082219556466857*I, -0.750453175769104012864271860 94108607489 + 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 837196 - 1.5701452385894131769052374806001981109*I; 1, 1.6829412935943127761 629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.750453175 76910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, - 0.78742068874775359433940488309213323160 + 2.1336633893126618034168454610457 936016*I, 1.2658732110596551455718089553258673705 - 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]]], [-1.0891151457205048250249527946671612684, -0.13838372073406036365047 976417441696637 + 0.49181637657768643499753285514741525107*I, 1.682941293594 3127761629561615079976006 + 2.0500351226010726172974286983598602164*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) [[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 2837196 - 1.5701452385894131769052374806001981109*I; 1, 1.682941293594312776 1629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.75045317 576910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, -0.78742068874775359433940488309213323160 + 2.133663389312661803416845461045 7936016*I, 1.2658732110596551455718089553258673705 - 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]]], [-1.0891151457205048250249527946671612684, -0.1383837207340603636504 7976417441696637 + 0.49181637657768643499753285514741525107*I, 1.68294129359 43127761629561615079976006 + 2.0500351226010726172974286983598602164*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)] ? nf3=nfinit(x^6+108); ? nf4=nfinit(x^3-10*x+8) [x^3 - 10*x + 8, [3, 0], 568, 2, [[1, -0.36332823793268357037416860931988791 957, -3.1413361156553641347759399165844441384; 1, -1.76155718183189058754537 11274124874988, 2.6261980685272936133764995500786243868; 1, 3.12488541976457 41579195397367323754184, -0.48486195287192947860055963349418024847], [1, -0. 36332823793268357037416860931988791957, -3.141336115655364134775939916584444 1384; 1, -1.7615571818318905875453711274124874988, 2.62619806852729361337649 95500786243868; 1, 3.1248854197645741579195397367323754184, -0.4848619528719 2947860055963349418024847], [1, 0, -3; 1, -2, 3; 1, 3, 0], [3, 1, -1; 1, 13, -5; -1, -5, 17], [284, 76, 46; 0, 2, 0; 0, 0, 1], [98, -6, 4; -6, 25, 7; 4, 7, 19], [284, [60, 418, -204; 105, 270, -2; 1, 104, -46]]], [-3.50466435358 80477051501085259043320579, 0.86464088669540302583112842266613688801, 2.6400 234668926446793189801032381951699], [1, 1/2*x^2 + x - 3, -1/2*x^2 + 3], [1, 0, 6; 0, 1, 0; 0, 1, -2], [1, 0, 0, 0, 4, -2, 0, -2, 6; 0, 1, 0, 1, 2, 0, 0, 0, -2; 0, 0, 1, 0, 1, -1, 1, -1, -1]] ? 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, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.71246530518434397468087951060 61300698 + 9.4247779607693797153879301498385086522*I; 2.71246530518434397468 08795106061300698 + 6.2831853071795864769252867665590057686*I], [-0.92212354 848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.70148550268542821846861610071436 900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.50057980363245 587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.623 6090511720428168202836906902792025, -0.5788359042095875039617797232424909750 4, -0.34328764427702709438988786673341921877 + 3.141592653589793238462643383 2795028842*I, 0.066178301882745732185368492323164193427 + 3.1415926535897932 384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.922123 54848661459835166758997591019383, 1.4227033521190704721778709033666269682, - 0.70148550268542821846861610071436900869 + 3.1415926535897932384626433832795 028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.6236090511720 428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.5788 3590420958750396177972324249097504, 0.34328764427702709438988786673341921877 , -0.066178301882745732185368492323164193427, 0.9883018503693603305370360822 9907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57 ; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, - 2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0] ]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.066372975210777963595931024670 5326059; 1, 8.0663729752107779635959310246705326059], [1, -7.066372975210777 9635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.06637297521077796359 59310246705326059], [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]], [[-0.92212354848661459835166758997591019383 + 3.1 415926535897932384626433832795028842*I, 0.9221235484866145983516675899759101 9383]]], 0] ? setrand(1);bnfinit(x^2-x-100000,1) [Mat(5), Mat([3, 2, 1, 2, 0, 3, 2, 3, 3, 2, 0, 0, 4, 1, 3, 2, 2, 3]), [-129. 82045011403975460991182396195022419 - 3.234427763 E-65*I; 129.82045011403975 460991182396195022419 + 1.513356110 E-65*I], [-41.81126458912994339333950225 8694361489 + 6.2831853071795864769252867665590057684*I, 9.239900414790228981 6376260438840931575 + 6.2831853071795864769252867665590057684*I, -11.8746098 81075406725097315997431161032 + 3.1415926535897932384626433832795028842*I, 0 , 598.05108556627860067458199150717266631 + 6.283185307179586476925286766559 0057684*I, -194.73067517105963191486773594292533629 + 3.14159265358979323846 26433832795028842*I, -289.57755493613404588806583418516364884 + 3.1415926535 897932384626433832795028842*I, 102.98937362955842429020308089254908188 + 9.4 9556775 E-66*I, -404.44153844676787690336623107514389175 + 3.141592653589793 2384626433832795028842*I, 484.20828704532476310708802954016117339 + 3.141592 6535897932384626433832795028842*I, 123.08269893574406654913158801089558608 + 6.2831853071795864769252867665590057684*I, -731.254381612670293662138025288 99365727, 601.43393149863053905222620132704343308 + 6.2831853071795864769252 867665590057684*I, 1093.4420050106303665241166125712749392 + 3.1415926535897 932384626433832795028842*I, -745.79191925764104608772064294411862807 + 3.141 5926535897932384626433832795028842*I, -671.206766092812650930409714233567335 50, 239.93415116156344370733474008902230144 + 3.1415926535897932384626433832 795028842*I, 652.97854421667665555630760228878662857 + 3.1415926535897932384 626433832795028842*I, -1733.3534097181246358289416962430827836; 41.811264589 129943393339502258694361489 + 8.30862178 E-66*I, -9.239900414790228981637626 0438840931575 + 3.1415926535897932384626433832795028842*I, 11.87460988107540 6725097315997431161032 + 6.2831853071795864769252867665590057684*I, 0, -598. 05108556627860067458199150717266631 + 3.141592653589793238462643383279502884 2*I, 194.73067517105963191486773594292533629 + 3.798227099 E-65*I, 289.57755 493613404588806583418516364884 + 4.747783872 E-65*I, -102.989373629558424290 20308089254908188 + 3.1415926535897932384626433832795028842*I, 404.441538446 76787690336623107514389175 + 5.697340648 E-65*I, -484.2082870453247631070880 2954016117339 + 6.2831853071795864769252867665590057684*I, -123.082698935744 06654913158801089558608 + 3.1415926535897932384626433832795028842*I, 731.254 38161267029366213802528899365727 + 1.139468130 E-64*I, -601.4339314986305390 5222620132704343308 + 6.2831853071795864769252867665590057684*I, -1093.44200 50106303665241166125712749392 + 3.1415926535897932384626433832795028842*I, 7 45.79191925764104608772064294411862807 + 3.141592653589793238462643383279502 8842*I, 671.20676609281265093040971423356733550 + 3.141592653589793238462643 3832795028842*I, -239.93415116156344370733474008902230144 + 6.28318530717958 64769252867665590057684*I, -652.97854421667665555630760228878662857 + 3.1415 926535897932384626433832795028842*I, 1733.3534097181246358289416962430827836 + 2.278936259 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]], [31, [23, 1]~, 1, 1, [7, 100000; 1, 8]], [31, [38, 1]~, 1, 1, [-8, 100000; 1 , -7]], [17, [14, 1]~, 1, 1, [2, 100000; 1, 3]], [17, [19, 1]~, 1, 1, [-3, 1 00000; 1, -2]], [23, [-7, 1]~, 1, 1, [6, 100000; 1, 7]], [23, [6, 1]~, 1, 1, [-7, 100000; 1, -6]], [29, [-14, 1]~, 1, 1, [13, 100000; 1, 14]], [29, [13, 1]~, 1, 1, [-14, 100000; 1, -13]], [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 - 10000 0, [2, 0], 400001, 1, [[1, -315.72816130129840161392089489603747004; 1, 316. 72816130129840161392089489603747004], [1, -315.72816130129840161392089489603 747004; 1, 316.72816130129840161392089489603747004], [1, -316; 1, 317], [2, 1; 1, 200001], [400001, 200000; 0, 1], [200001, -1; -1, 2], [400001, [200000 , 100000; 1, 200001]]], [-315.72816130129840161392089489603747004, 316.72816 130129840161392089489603747004], [1, x], [1, 0; 0, 1], [1, 0, 0, 100000; 0, 1, 1, 1]], [[5, [5], [[2, 1; 0, 1]]], 129.8204501140397546099118239619502241 9, 1, [2, -1], [379554884019013781006303254896369154068336082609238336*x + 1 19836165644250789990462835950022871665178127611316131167]], [Mat(1), [[0, 0] ], [[-41.811264589129943393339502258694361489 + 6.28318530717958647692528676 65590057684*I, 41.811264589129943393339502258694361489 + 8.30862178 E-66*I]] ], 0] ? \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, 1, 1]), [9, 15, 16, 33, 39, 17, 10, 57, 69], [2, -1], [[0, 1, 0]~, [ 5, 3, 1]~], [[[4, -1, 0]~, [1, -1, 0]~, [-2, -1, 0]~, [1, 1, 0]~, [10, 5, 1] ~, [3, 1, 0]~, [3, 0, 0]~, [7, 2, 0]~, [-2, -1, 1]~], 0]] ? \p38 realprecision = 38 significant digits ? bnr=bnrinit(bnf,[[5,3;0,1],[1,0]],1) [[Mat(3), Mat([1, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.7124653051843439746808795106 061300698 + 9.4247779607693797153879301498385086522*I; 2.7124653051843439746 808795106061300698 + 6.2831853071795864769252867665590057686*I], [-0.9221235 4848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.7014855026854282184686161007143 6900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.5005798036324 5587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.62 36090511720428168202836906902792025, -0.578835904209587503961779723242490975 04, -0.34328764427702709438988786673341921877 + 3.14159265358979323846264338 32795028842*I, 0.066178301882745732185368492323164193427 + 3.141592653589793 2384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.92212 354848661459835166758997591019383, 1.4227033521190704721778709033666269682, -0.70148550268542821846861610071436900869 + 3.141592653589793238462643383279 5028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.623609051172 0428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.578 83590420958750396177972324249097504, 0.3432876442770270943898878667334192187 7, -0.066178301882745732185368492323164193427, 0.988301850369360330537036082 29907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 5 7; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, -2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0 ]]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.06637297521077796359593102467 05326059; 1, 8.0663729752107779635959310246705326059], [1, -7.06637297521077 79635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7 ; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.0663729752107779635 959310246705326059], [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]], [[-0.92212354848661459835166758997591019383 + 3. 1415926535897932384626433832795028842*I, 0.922123548486614598351667589975910 19383]]], [0, [Mat([[5, 1]~, 1])]]], [[[5, 3; 0, 1], [1, 0]], [8, [4, 2], [2 , [-4, 0]~]], Mat([[5, [-2, 1]~, 1, 1, [1, 1]~], 1]), [[[[4], [[2, 0]~], [[2 , 0]~], [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]] ? rnfinit(nf2,x^5-x-2) [x^5 - x - 2, [], [[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.75487766624669276004950889635852869190, 1.324717957244746025960908 8544780973407; 1, -0.87743883312334638002475444817926434595 - 0.744861766619 74423659317042860439236724*I, -0.66235897862237301298045442723904867037 + 0. 56227951206230124389918214490937306150*I], [1, 0.754877666246692760049508896 35852869190, 1.3247179572447460259609088544780973407; 1, -1.6223005997430906 166179248767836567132, -0.10007946656007176908127228232967560887; 1, -0.1325 7706650360214343158401957487197871, -1.2246384906846742568796365721484217319 ], [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]]], [1.3247179572447460259609088544780973407, -0.662358978622373 01298045442723904867037 + 0.56227951206230124389918214490937306150*I], [1, y ^2 - 1, y], [1, 0, 1; 0, 0, 1; 0, 1, 0], [1, 0, 0, 0, 0, 1, 0, 1, 1; 0, 1, 0 , 1, -1, 0, 0, 0, 1; 0, 0, 1, 0, 1, 0, 1, 0, 0]], [x^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 + 1 89*x^3 + 144*x^2 + 25*x + 1, Mod(39516536165538345/83718587879473471*x^14 - 6500512476832995/83718587879473471*x^13 - 196215472046117185/837185878794734 71*x^12 + 229902227480108910/83718587879473471*x^11 + 237380704030959181/837 18587879473471*x^10 - 1064931988160773805/83718587879473471*x^9 - 2065708667 1714300/83718587879473471*x^8 + 1772885205999206010/83718587879473471*x^7 + 5952033217241102348/83718587879473471*x^6 - 4838840187320655696/837185878794 73471*x^5 + 5180390720553188700/83718587879473471*x^4 - 8374015687535120430/ 83718587879473471*x^3 + 8907744727915040221/83718587879473471*x^2 + 41559766 64123434381/83718587879473471*x + 318920215718580450/83718587879473471, 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), -1], 0] ? bnfcertify(bnf) 1 ? setrand(1);bnfinit(x^2-x-100000,1).fu [Mod(379554884019013781006303254896369154068336082609238336*x + 119836165644 250789990462835950022871665178127611316131167, x^2 - x - 100000)] ? setrand(1);bnfinit(x^4+24*x^2+585*x+1791,,[0.1,0.1]) [Mat(4), Mat([1, 1, 2, 2, 3, 2, 2, 1, 3, 1, 3]), [3.794126968821658934140827 4220859400302 + 4.4849227478109716392557206258848340690*I; -3.79412696882165 89341408274220859400303 - 0.29613254302458065463886278151216355668*I], [1.86 27388728631440477260896482724058214 + 1.302127930155071449698332731720990992 0*I, -2.1252701833646858583118137135844245978 + 12.3087752031016904010866752 84585052448*I, 0.E-38 + 11.899424269855508723178392022414809397*I, -0.965694 04797925744320736888690676710446 + 10.451374429932923985994772355489506184*I , 0.93136943643157202386304482413620291066 + 1.05970182017512814722335450055 22512103*I, 3.9880090562278299060379033618568304192 + 2.22666968591621823313 44124909571522207*I, 1.1866112128284250300329626792760349086 + 1.53670691856 77180597127956706636636203*I, 0.67612766003471901769312696899637091276 + 5.5 634785705759693161966392672477025990*I, -1.124297501162687448712868198155804 1465 + 5.4047443910152126451848347441281753399*I, 2.987036374025831496438957 8464282099678 + 2.6656965945104158321529693145204519614*I, 0.185226091246709 92638186978112691957310 + 6.8174740759401753323716105568013780333*I, 1.67751 27816164341213442198671454862483 + 2.0449585535924932418120615942814425547*I ; -1.8627388728631440477260896482724058213 + 4.40766710140305359684665691421 15414722*I, 2.1252701833646858583118137135844245978 + 0.25759541125748255276 389824853295908846*I, 0.E-38 + 11.899424269855508723178392022414809397*I, 0. 96569404797925744320736888690676710447 + 1.828301046615518252665652617315268 7005*I, -0.93136943643157202386304482413620291066 + 2.6124714057991192207975 165917975264503*I, -3.9880090562278299060379033618568304191 + 4.817018034649 2352747549401763817845238*I, -1.1866112128284250300329626792760349086 + 7.11 62481561999603897708013584929778392*I, -0.6761276600347190176931269689963709 1275 + 3.0894765041917091332869577619089388604*I, 1.124297501162687448712868 1981558041465 + 0.69662231985168015178245507209625882934*I, -2.9870363740258 314964389578464282099678 + 10.479357836921930472703673169042918952*I, -0.185 22609124670992638186978112691957310 + 0.075884278933757561441547351857249422 592*I, -1.6775127816164341213442198671454862482 + 11.89208752184689315989044 8981716121646*I], [[7, [-2, -4, -2, 1]~, 1, 1, [-2, -3, -14, -37; 2, 3, 35, 23; -2, -3, 0, -2; 3, 1, 0, 3]], [7, [-1, -4, -2, 1]~, 1, 1, [-1, 4, 2, 33; -2, -6, -31, -32; 1, 3, -2, 2; -3, -2, -1, -6]], [7, [2, 0, 3, -1]~, 1, 1, [ 6, -5, 52, 7; 0, 7, -7, 49; 4, -1, 2, 0; 1, 5, 4, 7]], [3, [1, 0, 1, 0]~, 4, 1, [0, -3, 15, -6; 1, 2, 5, 23; 1, -1, -1, -1; 1, 2, 2, 2]], [19, [-8, -4, -2, 1]~, 2, 1, [-9, -13, 36, -14; 8, 1, 6, 61; 3, -2, -12, -8; 2, 5, 11, 1]] , [7, [3, -1, -1, 3]~, 1, 1, [3, -5, 26, -3; 2, 6, 1, 33; 2, -1, 1, -2; 1, 3 , 4, 6]], [13, [-4, -4, -2, 1]~, 1, 1, [-5, 2, 30, -17; -6, -8, 23, 42; 1, - 3, -6, 6; 3, 4, -5, -8]], [13, [-3, -4, -2, 1]~, 1, 1, [5, -15, 88, -25; 4, 14, 21, 123; 6, -5, -1, -4; 5, 11, 10, 14]], [13, [5, -4, -2, 1]~, 1, 1, [-3 , -12, 76, 2; 4, 3, -6, 84; 6, -2, -9, -4; 2, 8, 10, 3]], [13, [6, -4, -2, 1 ]~, 1, 1, [-1, 9, 2, 46; -6, -11, -40, -49; 1, 4, -2, 6; -4, -3, -5, -11]], [19, [-7, -4, -2, 1]~, 1, 1, [-1, -8, 19, -77; 1, 8, 76, 96; -1, -8, 0, -1; 8, 7, 0, 8]], [19, [8, -4, -2, 1]~, 1, 1, [4, 13, -124, 0; 0, 0, 0, -133; -9 , 4, 13, 0; -4, -13, -9, 0]]], 0, [x^4 + 24*x^2 + 585*x + 1791, [0, 2], 1898 1, 3087, [[1, 0.50000000000000000000000000000000000000 - 0.86602540378443864 676372317075293618348*I, -3.5933488079472828155742243261531931905 - 0.983450 02948048980529510074183097754868*I, -1.6483671128563006823406123980207685802 + 2.6202063376006319767212962440086284032*I; 1, 0.5000000000000000000000000 0000000000000 - 0.86602540378443864676372317075293618348*I, 3.09334880794728 28155742243261531931905 + 0.11742462569605115853137757107804136521*I, 2.6483 671128563006823406123980207685801 - 2.6202063376006319767212962440086284032* I], [1, -0.36602540378443864676372317075293618347, -4.5767988374277726208693 250679841707391, 0.97183922474433129438068384598785982306; 1, 1.366025403784 4386467637231707529361835, -2.6098987784667930102791235843222156418, -4.2685 734504569326590619086420293969833; 1, -0.36602540378443864676372317075293618 347, 3.2107734336433339741056018972312345557, 0.0281607752556687056193161540 12140176947; 1, 1.3660254037844386467637231707529361835, 2.97592418225123165 70428467550751518253, 5.2685734504569326590619086420293969833], [1, 0, -5, 1 ; 1, 1, -3, -4; 1, 0, 3, 0; 1, 1, 3, 5], [4, 2, -1, 2; 2, -2, -2, 1; -1, -2, 43, 34; 2, 1, 34, -8], [2109, 363, 183, 1236; 0, 3, 0, 1; 0, 0, 3, 1; 0, 0, 0, 1], [317, 360, -17, 52; 360, -700, -6, -23; -17, -6, 12, 46; 52, -23, 46 , -58], [2109, [-413, -643, 6915, 2254; 61, -351, -2315, 5303; 581, -1, -994 , -61; 1, 582, 642, -351]]], [4.5383305030382649488078362542856178008 + 8.05 12080116993661743663904106823282345*I, -4.5383305030382649488078362542856178 008 + 0.60904602614502029327084129684703360027*I], [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/10 29*x^3 + 170/1029*x^2 - 429/343*x - 2951/343], [1, 1, 0, -390; 0, -4, -39, - 57; 0, -2, 0, 99; 0, 1, 15, 9], [1, 0, 0, 0, 0, -1, -1, -1, 0, -1, 12, 4, 0, -1, 4, -9; 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, -4, 9, 0, 1, 9, 13; 0, 0, 1, 0, 0, 0, 0, -1, 1, 0, -1, 0, 0, -1, 0, 0; 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1]], [[4, [4], [[7, 2, 3, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]]], 3. 7941269688216589341408274220859400302, 1, [6, 10/1029*x^3 - 13/343*x^2 + 165 /343*x + 1478/343], [4/1029*x^3 + 53/1029*x^2 + 66/343*x + 111/343]], [Mat(- 1), [[1.9459101490553133051053527434431797296 + 3.52184386028272675394467633 36694683721*I, 1.9459101490553133051053527434431797296 + 3.52184386028272675 39446763336694683721*I]], [[5.9209017233581091726953213255003130972 + 12.785 247510975835566080372602956882497*I, 9.6463794690843972681475006220451247399 + 9.6797083397278534189320484204663320164*I]]], 0] ? 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)]~ ? \p19 realprecision = 19 significant digits ? bnfinit(sbnf) [Mat(2), Mat([1, 1, 0, 1, 0, 1, 1, 1]), [1.173637103435061715 + 3.1415926535 89793239*I, -4.562279014988837911 + 3.141592653589793239*I; -2.6335434327389 76050 + 3.141592653589793239*I, 1.420330600779487358 + 3.141592653589793239* I; 1.459906329303914335, 3.141948414209350544], [1.246346989334819161, 0.540 4006376129469728, -0.6926391142471042845, 0.004375616572659815433 + 3.141592 653589793239*I, -0.8305625946607188642 + 3.141592653589793239*I, -1.99005644 5584799713 + 3.141592653589793239*I, 0, -1.977791147836553954, 0.36772620140 27817707; 0.6716827432867392935, -0.8333219883742404172, -0.2461086674077943 078 + 3.141592653589793239*I, -0.8738318043071131265, -1.552661549868775854, 0.5379005671092853266, 0, 0.5774919091398324093, 0.9729063188316092381 + 3. 141592653589793239*I; -1.918029732621558454 + 3.141592653589793239*I, 0.2929 213507612934446 + 3.141592653589793239*I, 0.9387477816548985924 + 3.14159265 3589793239*I, 0.8694561877344533112, 2.383224144529494719, 1.452155878475514 387, 0, 1.400299238696721545, -1.340632520234391008 + 3.141592653589793239*I ], [[3, [-1, 1, 0]~, 1, 1, [1, 1, 1]~], [5, [-1, 1, 0]~, 1, 1, [0, 1, 1]~], [5, [2, 1, 0]~, 1, 1, [1, -2, 1]~], [11, [1, 1, 0]~, 1, 1, [-3, -1, 1]~], [1 3, [19, 1, 0]~, 1, 1, [-2, -6, 1]~], [5, [3, 1, 0]~, 1, 1, [2, 2, 1]~], [3, [10, 1, 1]~, 1, 2, [-1, 1, 0]~], [19, [-6, 1, 0]~, 1, 1, [6, 6, 1]~], [23, [ -10, 1, 0]~, 1, 1, [-7, 10, 1]~]]~, 0, [x^3 - x^2 - 14*x - 1, [3, 0], 10889, 1, [[1, -3.233732695981516673, 4.690759845041404812; 1, -0.0718235090274363 6345, -8.923017874523549404; 1, 4.305556205008953037, 5.232258029482144592], [1, -3.233732695981516673, 4.690759845041404812; 1, -0.07182350902743636345 , -8.923017874523549404; 1, 4.305556205008953037, 5.232258029482144592], [1, -3, 5; 1, 0, -9; 1, 4, 5], [3, 1, 1; 1, 29, 8; 1, 8, 129], [10889, 5698, 89 94; 0, 1, 0; 0, 0, 1], [3677, -121, -21; -121, 386, -23; -21, -23, 86], [108 89, [1899, 46720, 5235; 5191, 7095, 25956; 1, 5191, 1895]]], [-3.23373269598 1516673, -0.07182350902743636345, 4.305556205008953037], [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.34800724602768001, 1, [2, -1], [x, x^2 + 2*x - 4]], [Mat(1), [[0, 0, 0]], [[1.246346989334819161, 0.6716827432867392935, -1.918029732621558454 + 3.141592653589793239*I]]], [[[4, -1, 0]~, [1, -1, 0]~, [-2, -1, 0]~, [1, 1, 0]~, [10, 5, 1]~, [3, 1, 0]~, [3, 0, 0]~, [7, 2, 0]~, [-2, -1, 1]~], 0]] ? \p38 realprecision = 38 significant digits ? bnfnarrow(bnf) [3, [3], [[3, 2; 0, 1]]] ? bnfsignunit(bnf) [-1] [1] ? bnr2=bnrinit(bnf,[[25,13;0,1],[1,1]],1) [[Mat(3), Mat([1, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.7124653051843439746808795106 061300698 + 9.4247779607693797153879301498385086522*I; 2.7124653051843439746 808795106061300698 + 6.2831853071795864769252867665590057686*I], [-0.9221235 4848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.7014855026854282184686161007143 6900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.5005798036324 5587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.62 36090511720428168202836906902792025, -0.578835904209587503961779723242490975 04, -0.34328764427702709438988786673341921877 + 3.14159265358979323846264338 32795028842*I, 0.066178301882745732185368492323164193427 + 3.141592653589793 2384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.92212 354848661459835166758997591019383, 1.4227033521190704721778709033666269682, -0.70148550268542821846861610071436900869 + 3.141592653589793238462643383279 5028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.623609051172 0428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.578 83590420958750396177972324249097504, 0.3432876442770270943898878667334192187 7, -0.066178301882745732185368492323164193427, 0.988301850369360330537036082 29907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 5 7; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, -2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0 ]]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.06637297521077796359593102467 05326059; 1, 8.0663729752107779635959310246705326059], [1, -7.06637297521077 79635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7 ; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.0663729752107779635 959310246705326059], [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]], [[-0.92212354848661459835166758997591019383 + 3. 1415926535897932384626433832795028842*I, 0.922123548486614598351667589975910 19383]]], [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, 1]~], 2]), [[[[4 ], [[2, 0]~], [[2, 0]~], [Vecsmall([0, 0])], 1], [[5], [[6, 0]~], [[6, 0]~], [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]], [1], Mat([1, -3, -6, -6]), [12, [12], [[3, 2; 0, 1]]], [[0, 2, 0; -1, 10, 0], [- 2, 0; 0, -10], 2]] ? 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(nf4,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, -1, -1, -1, 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] [[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, [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]] ? 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, -1, -1, -1, 0]~] 1] [[5, [-1, 0, 0, 0, 2]~, 4, 1, [2, 2, 1, 2, 1]~] 3] [[5, [2, 0, 0, 0, -2]~, 1, 1, [2, 0, 3, 0, 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], [[1, 0, 2]~], [[1, 0, 2]~], [Vecs mall([])], 1], [[3, 3, 3], [[4, 0, 0]~, [1, 3, 0]~, [1, 0, 3]~], [[-23, 0, 0 ]~, [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, 0, 0]~, [1, 9, 0]~, [ 1, 0, 9]~], [[-17, 0, 0]~, [1, -18, 0]~, [1, 0, -18]~], [Vecsmall([]), Vecsm all([]), Vecsmall([])], [1/9, 0, 0; 0, 1/9, 0; 0, 0, 1/9]]], [[], [], []]], [468, 469, 0, 0, -728, 0, 0, -546; 0, 0, 1, 0, -8, -6, 0, -6; 0, 0, 0, 1, -8 , 0, -6, -6]] ? ideallog(nf2,y,bid) [1264, 0, 7]~ ? 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, 0, 0, 1, 1]~], [2, [12, -4, -2, 11, 3]~, 1, 4, [1, 0, 1, 0, 0]~]] ? idealprimedec(nf,3) [[3, [1, 0, 1, 0, 0]~, 1, 1, [1, -1, -1, -1, 0]~], [3, [1, 1, 1, 0, 0]~, 2, 2, [0, 2, 2, 1, 0]~]] ? 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], [[1, 1, 0]~], [[1, - 27, 0]~], [Vecsmall([])], 1]], [[[26], [[2, 2, 0]~], [[-25, 2, 0]~], [Vecsma ll([])], 1], [[3, 3, 3], [[4, 0, 0]~, [1, 3, 0]~, [1, 0, 3]~], [[-23, 0, 0]~ , [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, 0, 0]~, [1, 9, 0]~, [1, 0, 9]~], [[-17, 0, 0]~, [1, -18, 0]~, [1, 0, -18]~], [Vecsmall([]), Vecsmal l([]), Vecsmall([])], [1/9, 0, 0; 0, 1/9, 0; 0, 0, 1/9]]], [[], [], []]], [4 68, 469, 0, 0, -910, 0, 0, -1092; 0, 0, 1, 0, -3, -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, 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]]] ? 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, 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]]] ? 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,[as,[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 - 6*x^3 + 6*x^2 + 13*x - 5, x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1, x^5 - x^4 + 4*x^3 - 2*x^2 + x - 1, x^5 + 4*x^3 - 4*x^2 + 8*x - 8] ? polred(x^4-28*x^3-458*x^2+9156*x-25321,3) [1 x - 1] [1/115*x^2 - 14/115*x - 327/115 x^2 - 10] [2/897*x^3 - 14/299*x^2 - 1171/897*x + 9569/897 x^4 - 32*x^2 + 6] [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 - 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 + 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 - 2*x^4 - 62*x^3 + 85*x^2 + 818*x + 1, x^5 - 2*x^4 - 53*x^3 - 46 *x^2 + 508*x + 913, x^5 - 2*x^4 - 13*x^3 + 37*x^2 - 21*x - 1, x^5 - x^4 - 52 *x^3 - 197*x^2 - 273*x - 127] ? polred(p2,1,fa) [x - 1, x^5 - 2*x^4 - 62*x^3 + 85*x^2 + 818*x + 1, x^5 - 2*x^4 - 53*x^3 - 46 *x^2 + 508*x + 913, x^5 - 2*x^4 - 13*x^3 + 37*x^2 - 21*x - 1, x^5 - x^4 - 52 *x^3 - 197*x^2 - 273*x - 127] ? 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 - 363*x - 2663, 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.091666666666666666666666666666666666678 ? zetak(nfz,1.5+3*I) 0.88324345992059326405525724366416928953 - 0.2067536250233895222724230899142 7939006*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(229, 31609, -951, 0.E-48)], 2800.62525190701607648637062173707 45514] ? sizebyte(%) 152 ? getheap [175, 113027] ? print("Total time spent: ",gettime); Total time spent: 116 pari-2.5.5/src/test/32/rnfkummer0000644000175000017500000002453312147140047015036 0ustar billbill *** Warning: new stack size = 20000000 (19.073 Mbytes). 1 x^3 - 3*x + (311966908973076337621386134331160172204342586416124670608925118 891054626041140773202736320154459*y^3 + 353063352389554001682687119453818170 6037942949744617490323977317410115601935483409467616193640403*y^2 + 17210405 7429136777118089803231860501017482976207967700735538913959375232983366119995 5887821919825*y - 2083508953756903712768418518643346615867879358567769676664 126023530945774273352544764950149886658) 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 + (-331787058087433622201490395582174260626191743561925/229919*y^3 - 127 70590263087881493273666791720172143285966373266850/229919*y^2 + 252530864067 347909495461855214867697325712170338053625/229919*y + 8545812265626423170117 078769382358637678369854706286990/229919)*x^3 + (741137384735896583917824566 9124241722802355845940782056765103016169253667483036742031571549849399425/22 9919*y^3 + 29908945080051595226543486406824904032006190612955218156914517507 4111867505102027879635068320637066600/229919*y^2 - 5427673470715491933831700 5016773634128825024048285936838150337968646533142409934071587113873717083663 75/229919*y - 20633401923387519441198186160203919441250546265727911426620743 5419118122791996003199652251159881598125045/229919)*x + (7638020439026102660 3726209569757354025230489081734562179986574362481919168447623758386674137753 27493758676186821213721110700/229919*y^3 + 308621038173264947077113847748600 3379236237659698105721640247168520395545493146764116750832176349329081219935 33001562805058390/229919*y^2 - 558771362710968743160330837452874349383528752 0018915557228915689750342781946272859808459225652606743877794154136802994071 229770/229919*y - 2130741031767490653486584754045229501874617343998574851888 12977585625860464126648103529066067410800528044936919772101513914073720/2299 19) 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 - 4633910*x^3 - 352959211304163606080220*x^2 + 4110573092104718915163940 5743785*x + 1252389138034185331199768653982538252594094777596 7 x^3 + (-240*y^5 + 594*y^4 - 1002*y^3 + 474*y^2 - 462*y - 504)*x + (528*y^5 - 1340*y^4 + 2302*y^3 - 1230*y^2 + 1174*y + 966) 8 x^5 + (-12490585381661544359255403301035053110061910*y^3 + 88753785204045614 72503422910872004290197460*y^2 + 6432039127327618730502928086755494337371796 10*y - 457038484130159980782436350930533714409061170)*x^3 + (-13402751428164 5340620300162483056350640850689292892267066826165512*y^3 + 95235243030030469 814112992330493778292557062830362488860799262053*y^2 + 690175992472503337590 1003506523314713919218011682438894990413482822*y - 4904148131739972327284545 793455166015180538153351582525198684659988)*x^2 + (-473979575575708881557088 56849994683849365520972511563824369572802678417823703951003630*y^3 + 3367932 3468496441220407209890566679520252152888549909181980050360738580514765560899 830*y^2 + 244076244894932600669105503748523340880310818979111099033902755459 2708168372793653934980*y - 1734320048033240933678067521047553381449799255523 887315704756124974424249211251806055445)*x + (888479132132125436437249142813 7413743146658454713780078075413546969837635616890304615115722308289473248381 8/5*y^3 - 631322057494452864618221700953863619523020575841378253933498629374 80952856334509099209369622841067534904427/5*y^2 - 45752319596243710576653560 1831075687685136958790100077326575099623318014513223892050404458305737184896 9400608/5*y + 32509990947484580403420755703092054732352560997472944663250483 78505864671503910959921397017511503388596960342/5) 9 x^3 + (-13512473865*y - 491304352371)*x + (1710942834201925*y + 622087144601 41926) 10 [x^3 + (-13512473865*y - 491304352371)*x + (-3356312100136324*y - 1220332187 06666997), x^3 + (-13512473865*y - 491304352371)*x + (1710942834201925*y + 6 2208714460141926), x^3 + (-13512473865*y - 491304352371)*x + (-5067254934338 249*y - 184241933166808923), x^3 - 3*x - 1] 11 x^5 - 10*x^3 + 20*x - 10 12 x^5 + (-4765941654868705920419593586878703269747443910292761667320/27*y^3 + 12377326963957769050169907799449802342616696593025278899880/27*y^2 + 9156375 4885043941876415000407442717910425544656584846908340/9*y - 69807413945909958 737090271240415146410317575079258649322980)*x^3 + (6451423090654457168258951 1351194450977164685449063098341641014670970987121547620768780/9*y^3 + 103888 5056939392143713886860303958374052024030744377976499254396211420837339260930 810730/9*y^2 + 7204576455294605320326104107342502483034902918239860127912033 50054151620992606858871040/3*y - 1949894339462550414934793879044197752851790 591620384696794570917612757675449488363778600)*x^2 + (3929295632822200815394 4803898489098128932032711550031730063444615456140056033652549074845456512471 411557758171410640/27*y^3 - 427972943345232137254913592671796727387567339451 65906036022185601826401891828657319973423738492464889809977337918730/27*y^2 - 58543936970899598172689704955617487044917082842108787996682681590606962124 0862081918848885137716222874222290434775860/9*y + 56758393921634675144943829 2125138096368610480521936480792433645673756696626324467760639279905138193353 501265459913630)*x + (-16588030084529273591749178628751783192593636062035926 3001581020460775240894723792010012760998422025119354978561747025310567908752 7217460110810154/27*y^3 - 38763841693484466059812330019519221076969732238673 8868860366528309211208861285467317969333279480995134477537152824954995739700 93980855830078159538/27*y^2 - 4843681866419016675318397390866680005599281490 6499946012258935482509582740111081439335464648592560089680906815045944138600 424070469912034951983348/9*y + 224216371038354157705777604673561016608169911 7007545534864995433938954691615603308177626247037067218367597753762959239283 9341371309530971255421334) 13 x^5 + (41675749815605474682300*y - 473011239937199627294510)*x^3 + (12987408 509128761747208433824766580*y - 114459000172186730474768920840594100)*x^2 + (-1901303847876681901370591794176695615698424100*y + 18032797337962677256486 556095959141093737663985)*x + (-50994788340520140686216889164131759223136164 496558335484*y + 448064359589646139039961812179554933382541180905578823300) 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/4*y^5 - 9/4*y^4 - 1/2*y^3 - 3/4*y^2 - 3/4*y + 3/2) 16 x^2 + (30237893533377177585274818309716447175*y^5 - 332498313903387415829914 313666675360297*y^4 + 58935557047612851360265142086661442617*y^3 - 117640120 973960296978686942015897120823*y^2 + 113867586930627879387621746872715126816 *y - 257526772651124939007698567207659716875) 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 + (4973/2*y^3 + 36285*y^2 - 107 6961/2*y + 2121130) 20 [x^3 - 3*x - 1] Total time spent: 21169 pari-2.5.5/src/test/32/nffactor0000644000175000017500000014632612147140047014637 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 + Mod(-y, y^2 + 1) 1] [x + Mod(y, y^2 + 1) 1] [x + Mod(-y, y^2 + 1) 1] [x + Mod(y, y^2 + 1) 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 [Mod(28870969412445129304/150333898582544875079637735*a^34 - 239104063973811 25246214047/902003391495269250477826410000*a^32 + 14082805809255777431889149 59/902003391495269250477826410000*a^30 - 47270903738475878949122441507/90200 3391495269250477826410000*a^28 + 1016201980774469757442024408441/90200339149 5269250477826410000*a^26 - 1653232481585973809555097282799/10022259905502991 6719758490000*a^24 + 30766570387863948626786349252629/1804006782990538500955 65282000*a^22 - 25494617146287004973995153489163/200445198110059833439516980 00*a^20 + 54269387427573548559506499935047/7843507752132776091111534000*a^18 - 4967271194565117464292207548275283/180400678299053850095565282000*a^16 + 14390821273796469411671423134660909/180400678299053850095565282000*a^14 - 16 637551485416921371399599192940627/100222599055029916719758490000*a^12 + 2184 42964149682251745527062058729581/902003391495269250477826410000*a^10 - 71504 782808114491609686387087461101/300667797165089750159275470000*a^8 + 13246357 6654385501140215626560461749/902003391495269250477826410000*a^6 - 4552113678 0059303695022254815264059/902003391495269250477826410000*a^4 + 4883454774574 976948426917348117/644288136782335178912733150*a^2 - 31947174916220852422727 719/91469478158982811558152, a^36 - 140*a^34 + 8402*a^32 - 288950*a^30 + 640 6703*a^28 - 97539585*a^26 + 1059042259*a^24 - 8396309325*a^22 + 49297808195* a^20 - 215811263825*a^18 + 704643601819*a^16 - 1705347924285*a^14 + 30170704 72643*a^12 - 3809285900925*a^10 + 3299709349267*a^8 - 1836758642090*a^6 + 58 5303753211*a^4 - 85409835875*a^2 + 3969153125), Mod(325135052707296657885896 3/4510016957476346252389132050000*a^34 - 224934549971331898950636911/2255008 478738173126194566025000*a^32 + 8860674919294055555049660713/150333898582544 8750796377350000*a^30 - 99557773024274624590944467659/5011129952751495835987 92450000*a^28 + 19366458770607880120052179046813/451001695747634625238913205 0000*a^26 - 285516842858115285212427862265807/451001695747634625238913205000 0*a^24 + 595519111738991674011764093345989/902003391495269250477826410000*a^ 22 - 4489547975447934229698580858261951/902003391495269250477826410000*a^20 + 1076139228842461035371382151402807/39217538760663880455557670000*a^18 - 11 124367147850754939979966580304871/100222599055029916719758490000*a^16 + 1479 061897966350800416026745438951477/4510016957476346252389132050000*a^14 - 315 0258572714802481572329123033742463/4510016957476346252389132050000*a^12 + 47 20650629432048287367394676298685961/4510016957476346252389132050000*a^10 - 4 777649748033279268548939533863439719/4510016957476346252389132050000*a^8 + 3 048859768911341351494073063483963897/4510016957476346252389132050000*a^6 - 5 42609961422709150427827731981252029/2255008478738173126194566025000*a^4 + 64 587456786717997350050100662819/1718101698086227143767288400*a^2 - 1657989958 32125073281674123/91469478158982811558152, a^36 - 140*a^34 + 8402*a^32 - 288 950*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 - 18367586 42090*a^6 + 585303753211*a^4 - 85409835875*a^2 + 3969153125), Mod(-704379081 794904012990253/9020033914952692504778264100000*a^35 - 185571858472598531261 171/501112995275149583598792450000*a^34 + 48715152518881440798956651/4510016 957476346252389132050000*a^33 + 462092978647254762515957747/9020033914952692 504778264100000*a^32 - 1438664992797585884326185341/225500847873817312619456 6025000*a^31 - 13648984531486738963024628227/4510016957476346252389132050000 *a^30 + 96938310360867353475048806483/4510016957476346252389132050000*a^29 + 919883530735586552464580524411/9020033914952692504778264100000*a^28 - 23265 1976540261816658545907611/501112995275149583598792450000*a^27 - 198750716628 37802701492211372933/9020033914952692504778264100000*a^26 + 3084532723611278 2336432658557121/4510016957476346252389132050000*a^25 + 97629122086975105817 272227332809/3006677971650897501592754700000*a^24 - 214249855748414994378468 87948389/300667797165089750159275470000*a^23 - 61057512827573393594268087407 4229/1804006782990538500955652820000*a^22 + 48401728645487982896973678955984 3/902003391495269250477826410000*a^21 + 1533419100031007894056656543524977/6 01335594330179500318550940000*a^20 - 115867185677361369373967739807791/39217 538760663880455557670000*a^19 - 1101904664343520893720157677667127/784350775 21327760911115340000*a^18 + 1537709883158934201041232269889911/1288576273564 67035782546630000*a^17 + 102435163177336591259551771572103159/18040067829905 38500955652820000*a^16 - 52922339838199964897013991241504027/150333898582544 8750796377350000*a^15 - 1511940075676759161409693048855920037/90200339149526 92504778264100000*a^14 + 48235573092787992694240830453221347/644288136782335 178912733150000*a^13 + 1072397626380076002236295333324062521/300667797165089 7501592754700000*a^12 - 168469447479250941117305882802587131/150333898582544 8750796377350000*a^11 - 4816022669775700225331001791553165721/90200339149526 92504778264100000*a^10 + 1491287229390570953499395745247369/1314873748535377 9161484350000*a^9 + 1622999198309123955156581806974277013/300667797165089750 1592754700000*a^8 - 327237997164237860693483056003293031/4510016957476346252 389132050000*a^7 - 3103794645076791741342476648584879777/9020033914952692504 778264100000*a^6 + 234832202947772004413604407002503923/90200339149526925047 78264100000*a^5 + 1103557826155591218607618557985611613/90200339149526925047 78264100000*a^4 - 375268653216574833833156819828029/902003391495269250477826 41000*a^3 - 49201004178902125753179356208497/2577152547129340715650932600*a^ 2 + 455861078300944766857933289/2134287823709598936356880*a + 33643899924545 7567382406693/365877912635931246232608, a^36 - 140*a^34 + 8402*a^32 - 288950 *a^30 + 6406703*a^28 - 97539585*a^26 + 1059042259*a^24 - 8396309325*a^22 + 4 9297808195*a^20 - 215811263825*a^18 + 704643601819*a^16 - 1705347924285*a^14 + 3017070472643*a^12 - 3809285900925*a^10 + 3299709349267*a^8 - 18367586420 90*a^6 + 585303753211*a^4 - 85409835875*a^2 + 3969153125), Mod(-457997268286 495201285601/9020033914952692504778264100000*a^35 - 155437231387909379055577 /1804006782990538500955652820000*a^34 + 63219462123808708551299959/902003391 4952692504778264100000*a^33 + 10732815328231466161638631/9020033914952692504 77826410000*a^32 - 1241268191638711501136747401/3006677971650897501592754700 000*a^31 - 162691836407833782279946/231996757071828510925366875*a^30 + 41671 559320168530327971893369/3006677971650897501592754700000*a^29 + 472202100389 4765857767375379/200445198110059833439516980000*a^28 - 268827453299542151937 7197948701/9020033914952692504778264100000*a^27 - 91447940232848524115401794 3217/1804006782990538500955652820000*a^26 + 39380597302365530060214378192779 /9020033914952692504778264100000*a^25 + 13404987653711757838118111598667/180 4006782990538500955652820000*a^24 - 81492696927754851227554074520033/1804006 782990538500955652820000*a^23 - 27755367080515496240602993106981/36080135659 8107700191130564000*a^22 + 608451862766595678082876478420347/180400678299053 8500955652820000*a^21 + 207309689387565154271678626939871/360801356598107700 191130564000*a^20 - 144141144819342089103549365967439/7843507752132776091111 5340000*a^19 - 49116300327361576889751394682183/1568701550426555218222306800 0*a^18 + 163228993853205803064485212811743/22271688678895537048835220000*a^1 7 + 1501366475076386034781931026134473/120267118866035900063710188000*a^16 - 192040496313746347169675964373314529/9020033914952692504778264100000*a^15 - 65378470826900674859623854989910833/1804006782990538500955652820000*a^14 + 400908998300724067746255602794046311/9020033914952692504778264100000*a^13 + 136351102083667187315285017348776623/1804006782990538500955652820000*a^12 - 586838332855949729229685411031808997/9020033914952692504778264100000*a^11 - 199368556080951864152805639007833629/1804006782990538500955652820000*a^10 + 578030985689012831826453965281320943/9020033914952692504778264100000*a^9 + 1 96244779045524955444897983850505039/1804006782990538500955652820000*a^8 - 35 7480334490463612280117630223936969/9020033914952692504778264100000*a^7 - 121 476601421295423170534909540278573/1804006782990538500955652820000*a^6 + 3062 4370220614590128641706307930719/2255008478738173126194566025000*a^5 + 104633 89029506180036157409002660637/451001695747634625238913205000*a^4 - 861866149 3592985666542036187341/4295254245215567859418221000*a^3 - 266859198823298552 776653451403/76360075470498984167435040*a^2 + 591232823580313844716106279/64 02863471128796809070640*a + 59236281207552249649513295/365877912635931246232 608, a^36 - 140*a^34 + 8402*a^32 - 288950*a^30 + 6406703*a^28 - 97539585*a^2 6 + 1059042259*a^24 - 8396309325*a^22 + 49297808195*a^20 - 215811263825*a^18 + 704643601819*a^16 - 1705347924285*a^14 + 3017070472643*a^12 - 38092859009 25*a^10 + 3299709349267*a^8 - 1836758642090*a^6 + 585303753211*a^4 - 8540983 5875*a^2 + 3969153125), Mod(457997268286495201285601/90200339149526925047782 64100000*a^35 - 155437231387909379055577/1804006782990538500955652820000*a^3 4 - 63219462123808708551299959/9020033914952692504778264100000*a^33 + 107328 15328231466161638631/902003391495269250477826410000*a^32 + 12412681916387115 01136747401/3006677971650897501592754700000*a^31 - 162691836407833782279946/ 231996757071828510925366875*a^30 - 41671559320168530327971893369/30066779716 50897501592754700000*a^29 + 4722021003894765857767375379/2004451981100598334 39516980000*a^28 + 2688274532995421519377197948701/9020033914952692504778264 100000*a^27 - 914479402328485241154017943217/1804006782990538500955652820000 *a^26 - 39380597302365530060214378192779/9020033914952692504778264100000*a^2 5 + 13404987653711757838118111598667/1804006782990538500955652820000*a^24 + 81492696927754851227554074520033/1804006782990538500955652820000*a^23 - 2775 5367080515496240602993106981/360801356598107700191130564000*a^22 - 608451862 766595678082876478420347/1804006782990538500955652820000*a^21 + 207309689387 565154271678626939871/360801356598107700191130564000*a^20 + 1441411448193420 89103549365967439/78435077521327760911115340000*a^19 - 491163003273615768897 51394682183/15687015504265552182223068000*a^18 - 163228993853205803064485212 811743/22271688678895537048835220000*a^17 + 15013664750763860347819310261344 73/120267118866035900063710188000*a^16 + 19204049631374634716967596437331452 9/9020033914952692504778264100000*a^15 - 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/9 020033914952692504778264100000*a^7 - 121476601421295423170534909540278573/18 04006782990538500955652820000*a^6 - 30624370220614590128641706307930719/2255 008478738173126194566025000*a^5 + 10463389029506180036157409002660637/451001 695747634625238913205000*a^4 + 8618661493592985666542036187341/4295254245215 567859418221000*a^3 - 266859198823298552776653451403/76360075470498984167435 040*a^2 - 591232823580313844716106279/6402863471128796809070640*a + 59236281 207552249649513295/365877912635931246232608, a^36 - 140*a^34 + 8402*a^32 - 2 88950*a^30 + 6406703*a^28 - 97539585*a^26 + 1059042259*a^24 - 8396309325*a^2 2 + 49297808195*a^20 - 215811263825*a^18 + 704643601819*a^16 - 1705347924285 *a^14 + 3017070472643*a^12 - 3809285900925*a^10 + 3299709349267*a^8 - 183675 8642090*a^6 + 585303753211*a^4 - 85409835875*a^2 + 3969153125), Mod(70437908 1794904012990253/9020033914952692504778264100000*a^35 - 18557185847259853126 1171/501112995275149583598792450000*a^34 - 48715152518881440798956651/451001 6957476346252389132050000*a^33 + 462092978647254762515957747/902003391495269 2504778264100000*a^32 + 1438664992797585884326185341/22550084787381731261945 66025000*a^31 - 13648984531486738963024628227/451001695747634625238913205000 0*a^30 - 96938310360867353475048806483/4510016957476346252389132050000*a^29 + 919883530735586552464580524411/9020033914952692504778264100000*a^28 + 2326 51976540261816658545907611/501112995275149583598792450000*a^27 - 19875071662 837802701492211372933/9020033914952692504778264100000*a^26 - 308453272361127 82336432658557121/4510016957476346252389132050000*a^25 + 9762912208697510581 7272227332809/3006677971650897501592754700000*a^24 + 21424985574841499437846 887948389/300667797165089750159275470000*a^23 - 6105751282757339359426808740 74229/1804006782990538500955652820000*a^22 - 4840172864548798289697367895598 43/902003391495269250477826410000*a^21 + 1533419100031007894056656543524977/ 601335594330179500318550940000*a^20 + 115867185677361369373967739807791/3921 7538760663880455557670000*a^19 - 1101904664343520893720157677667127/78435077 521327760911115340000*a^18 - 1537709883158934201041232269889911/128857627356 467035782546630000*a^17 + 102435163177336591259551771572103159/1804006782990 538500955652820000*a^16 + 52922339838199964897013991241504027/15033389858254 48750796377350000*a^15 - 1511940075676759161409693048855920037/9020033914952 692504778264100000*a^14 - 48235573092787992694240830453221347/64428813678233 5178912733150000*a^13 + 1072397626380076002236295333324062521/30066779716508 97501592754700000*a^12 + 168469447479250941117305882802587131/15033389858254 48750796377350000*a^11 - 4816022669775700225331001791553165721/9020033914952 692504778264100000*a^10 - 1491287229390570953499395745247369/131487374853537 79161484350000*a^9 + 1622999198309123955156581806974277013/30066779716508975 01592754700000*a^8 + 327237997164237860693483056003293031/451001695747634625 2389132050000*a^7 - 3103794645076791741342476648584879777/902003391495269250 4778264100000*a^6 - 234832202947772004413604407002503923/9020033914952692504 778264100000*a^5 + 1103557826155591218607618557985611613/9020033914952692504 778264100000*a^4 + 375268653216574833833156819828029/90200339149526925047782 641000*a^3 - 49201004178902125753179356208497/2577152547129340715650932600*a ^2 - 455861078300944766857933289/2134287823709598936356880*a + 3364389992454 57567382406693/365877912635931246232608, a^36 - 140*a^34 + 8402*a^32 - 28895 0*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^1 4 + 3017070472643*a^12 - 3809285900925*a^10 + 3299709349267*a^8 - 1836758642 090*a^6 + 585303753211*a^4 - 85409835875*a^2 + 3969153125)] [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 + Mod(-y^7 - 1, y^12 - y^11 + y^9 - y^8 + y^6 - y^4 + y^3 - y + 1) 1] [x + Mod(y^7 + 1, y^12 - y^11 + y^9 - y^8 + y^6 - y^4 + y^3 - y + 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 + Mod(-2/3*y + 1/3, y^2 - y + 1) 1] [x + Mod(2/3*y - 1/3, y^2 - y + 1) 1] *** nfroots: Warning: non-monic polynomial. Result of the form [nf,c]. [Mod(-2/3*y + 1/3, y^2 - y + 1), Mod(2/3*y - 1/3, y^2 - y + 1)] [x + Mod(-26388279066648/85070591730466729623209871765718171955*t^5 + 131941 395333267/85070591730466729623209871765718171955*t^4 + 967140655690823730462 71732/85070591730466729623209871765718171955*t^3 - 2901421967080321704410481 36/85070591730466729623209871765718171955*t^2 - 7443676776386824622360021639 7446118676/85070591730466729623209871765718171955*t + 7443676776373163760598 3666543681076444/85070591730466729623209871765718171955, t^6 - 6*t^5 - 32985 34883316*t^4 + 13194139533310*t^3 + 3626777458830693384585198*t^2 - 72535549 17667983838937052*t - 1329227995784915872903826851489644559) 1] [x^2 + Mod(26388279066648/85070591730466729623209871765718171955*t^5 - 13194 1395333267/85070591730466729623209871765718171955*t^4 - 96714065569082373046 271732/85070591730466729623209871765718171955*t^3 + 290142196708032170441048 136/85070591730466729623209871765718171955*t^2 + 744367677638682462236002163 97446118676/85070591730466729623209871765718171955*t - 744367677637316376059 83666543681076444/85070591730466729623209871765718171955, t^6 - 6*t^5 - 3298 534883316*t^4 + 13194139533310*t^3 + 3626777458830693384585198*t^2 - 7253554 917667983838937052*t - 1329227995784915872903826851489644559)*x + Mod(54/850 70591730466729623209871765718171955*t^5 + 19342813113869251167387394/8507059 1730466729623209871765718171955*t^4 - 77371252455674916762549976/85070591730 466729623209871765718171955*t^3 - 42535295865117307932921126639575760427/850 70591730466729623209871765718171955*t^2 + 8507059173077379678139195239172145 0758/85070591730466729623209871765718171955*t + 2338402619733698198712370953 5795926763206176932728/85070591730466729623209871765718171955, t^6 - 6*t^5 - 3298534883316*t^4 + 13194139533310*t^3 + 3626777458830693384585198*t^2 - 72 53554917667983838937052*t - 1329227995784915872903826851489644559) 1] x^6 + 10/7*x^5 - 867/49*x^4 - 76/245*x^3 + 3148/35*x^2 - 25944/245*x + 48771 /1225 Total time spent: 10569 pari-2.5.5/src/test/32/rfrac0000644000175000017500000000025612141040641014112 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] Total time spent: 3328 pari-2.5.5/src/test/32/select0000644000175000017500000000021011636712103014271 0ustar billbill[2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601] List([2, 3, 5]) List([2, 3, 5]) [1 2] [2 0] [0] [0] Total time spent: 10 pari-2.5.5/src/test/32/apply0000644000175000017500000000014512147140047014146 0ustar billbill[1, 4, 9, 16] [1 4] [9 16] 16*x^2 + 9*x + 4 List([1, 4, 9, 16]) List([1, 2]) Total time spent: 10 pari-2.5.5/src/test/32/stark0000644000175000017500000001623412147140047014153 0ustar billbill *** Warning: new stack size = 20000000 (19.073 Mbytes). 321: x^3 - x^2 - 4*x + 1 520: x^4 - 6*x^2 + 4 577: x^7 - 2*x^6 - 7*x^5 + 10*x^4 + 13*x^3 - 10*x^2 - x + 1 840: x^4 - 6*x^2 + 4 904: x^8 - x^7 - 16*x^6 + 3*x^5 + 71*x^4 + 6*x^3 - 110*x^2 - 20*x + 44 1009: x^7 - x^6 - 9*x^5 + 2*x^4 + 21*x^3 + x^2 - 13*x - 1 1129: x^9 - 3*x^8 - 10*x^7 + 38*x^6 + 5*x^5 - 107*x^4 + 58*x^3 + 78*x^2 - 60 *x - 1 1229: x^3 - x^2 - 7*x + 6 1297: x^11 - 5*x^10 - 4*x^9 + 54*x^8 - 53*x^7 - 127*x^6 + 208*x^5 + 69*x^4 - 222*x^3 + 29*x^2 + 56*x - 5 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 2920: x^12 - 2*x^11 - 23*x^10 + 46*x^9 + 161*x^8 - 340*x^7 - 382*x^6 + 960*x ^5 + 156*x^4 - 976*x^3 + 272*x^2 + 192*x - 64 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(249*y^2 - 22*y - 2983, y^3 - 12*y - 1)*x^5 + Mod(-78906*y^2 + 6575*y + 946331, y^3 - 12*y - 1)*x^4 + Mod(2611117 *y^2 - 217723*y - 31315230, y^3 - 12*y - 1)*x^3 + Mod(-27093232*y^2 + 225907 7*y + 324930439, y^3 - 12*y - 1)*x^2 + Mod(103641257*y^2 - 8641781*y - 12429 74520, y^3 - 12*y - 1)*x + Mod(-126674169*y^2 + 10562299*y + 1519209322, 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 - 12*y - 1, [5, y + 1]]: x^6 + Mod(249*y^2 - 22*y - 2983, y^3 - 12*y - 1)*x^5 + Mod(-78906*y^2 + 6575*y + 946331, y^3 - 12*y - 1)*x^4 + Mod(2611117 *y^2 - 217723*y - 31315230, y^3 - 12*y - 1)*x^3 + Mod(-27093232*y^2 + 225907 7*y + 324930439, y^3 - 12*y - 1)*x^2 + Mod(103641257*y^2 - 8641781*y - 12429 74520, y^3 - 12*y - 1)*x + Mod(-126674169*y^2 + 10562299*y + 1519209322, y^3 - 12*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^2 + Mod(-528*y - 1668, y^2 - 10)*x + Mod(2592*y + 8196, y^2 - 10), x^2 + Mod(-10088*y - 31900, y^2 - 10)*x + Mod(65200*y + 206180, y^2 - 10)] Total time spent: 47098 pari-2.5.5/src/test/32/multivar-mul0000644000175000017500000000000011636712103015445 0ustar billbillpari-2.5.5/src/test/32/round40000644000175000017500000003230712147140047014241 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 Total time spent: 24193 pari-2.5.5/src/test/32/analyz0000644000175000017500000000033412147140047014317 0ustar billbill echo = 1 (on) ? gettime;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)); ? getheap [6, 60] ? print("Total time spent: ",gettime); Total time spent: 16 pari-2.5.5/src/test/32/ellsea0000644000175000017500000000060511636712103014267 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 Total time spent: 11668 pari-2.5.5/src/test/32/ffisom0000644000175000017500000000362212147140047014307 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] pari-2.5.5/src/test/32/polred0000644000175000017500000000151112147140047014304 0ustar billbillx^7 + Mod(7*y - 7, y^2 - y - 1)*x^6 + Mod(-21*y + 28, y^2 - y - 1)*x^5 - 35* x^4 + Mod(35*y - 49, y^2 - y - 1)*x^3 + Mod(-7*y + 84, y^2 - y - 1)*x^2 + Mo d(-14*y + 21, y^2 - y - 1)*x + Mod(-y - 43, y^2 - y - 1) 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) *** 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 Total time spent: 2124 pari-2.5.5/src/test/32/equal0000644000175000017500000000003412200712517014122 0ustar billbill1 0 1 0 Total time spent: 4 pari-2.5.5/src/test/32/bezout0000644000175000017500000000141312147140047014330 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))] Total time spent: 6 pari-2.5.5/src/test/32/idealappr0000644000175000017500000000003411636712103014757 0ustar billbill[3, 0]~ Total time spent: 0 pari-2.5.5/src/test/32/thue0000644000175000017500000000077412141040641013767 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], [1, 1], [0, 1], [-1, -1], [0, -1]] [[1868, 514], [-4, -2]] [] [[5, 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]] Total time spent: 1080 pari-2.5.5/src/test/32/bnr0000644000175000017500000000022612147140047013602 0ustar billbill *** at top-level: bnrL1(bnrinit(bnfini *** ^-------------------- *** bnrL1: incorrect subgroup in bnrL1. Total time spent: 30 pari-2.5.5/src/test/32/modpr0000644000175000017500000000022712147140047014143 0ustar billbill *** at top-level: nfeltmulmodpr(nfinit *** ^-------------------- *** nfeltmulmodpr: incorrect prime ideal. Total time spent: 8 pari-2.5.5/src/test/32/elliptic0000644000175000017500000001641712147140047014637 0ustar billbill echo = 1 (on) ? gettime;ellinit([0,0,0,-1,0]) [0, 0, 0, -1, 0, 0, -2, 0, -1, 48, 0, 64, 1728, [1.0000000000000000000000000 000000000000, 0.E-48, -1.0000000000000000000000000000000000000]~, 2.62205755 42921198104648395898911194137, -2.6220575542921198104648395898911194137*I, 1 .1981402347355922074399224922803238782, 1.1981402347355922074399224922803238 782*I, 6.8751858180203728274900957798105571979] ? ellinit([0,0,0,-17,0],1) [0, 0, 0, -17, 0, 0, -34, 0, -289, 816, 0, 314432, 1728] ? 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, [0.83756543528332303 544481089907503024040, 0.26959443640544455826293795134926000405, -1.10715987 16887675937077488504242902445]~, 2.9934586462319596298320099794525081778, -2 .4513893819867900608542248318665252254*I, 0.94263855591362295176518779416067 539931, 1.3270305788796764757190502098362372906*I, 7.33813274078957673907072 10033323055880] ? 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, [-0.1624345647 1667696455518910092496975960, -0.73040556359455544173706204865073999595, -2. 1071598716887675937077488504242902445]~, -2.99345864623195962983200997945250 81778, 2.4513893819867900608542248318665252254*I, -0.94263855591362295176518 779416067539931, -1.3270305788796764757190502098362372906*I, 7.3381327407895 767390707210033323055880] ? apoint=ellchangepoint(apoint,[-1,1,2,3]) [1, 3] ? ellisoncurve(acurve,apoint) 1 ? ellglobalred(acurve) [37, [1, -1, 2, 2], 1] ? ellheight(acurve,apoint) 0.81778253183950144377417759611107234575 ? ellheight(acurve,apoint,1) 0.81778253183950144377417759611107234576 ? ellordinate(acurve,1) [8, 3] ? ellpointtoz(acurve,apoint) 0.72491221490962306778878739838332384646 + 0.E-49*I ? ellztopoint(acurve,%) [0.99999999999999999999999999999999999994 + 0.E-38*I, 2.99999999999999999999 99999999999999998 + 0.E-37*I] ? ellpow(acurve,apoint,10) [-28919032218753260057646013785951999/292736325329248127651484680640160000, 478051489392386968218136375373985436596569736643531551/158385319626308443937 475969221994173751192384064000000] ? ellwp(acurve,,,32) 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([0,0,0,-3,0]) [0, 0, 0, -3, 0, 0, -6, 0, -9, 144, 0, 1728, 1728, [1.7320508075688772935274 463415058723669, 0.E-48, -1.7320508075688772935274463415058723669]~, 1.99233 28995834907073368080310227454215, -1.9923328995834907073368080310227454215*I , 1.5768412268083121362312158419045774608, 1.5768412268083121362312158419045 774608*I, 3.9693903827627596663162680332564652025] ? 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, [0.8375654352833230 3544481089907503024040, 0.26959443640544455826293795134926000405, -1.1071598 716887675937077488504242902445]~, 2.9934586462319596298320099794525081778, - 2.4513893819867900608542248318665252254*I, 0.9426385559136229517651877941606 7539931, 1.3270305788796764757190502098362372906*I, 7.3381327407895767390707 210033323055880] ? l=elllseries(ccurve,2) 0.38157540826071121129371040958008663664 ? elllseries(ccurve,2,1.2)-l 2.292213984 E-37 ? tcurve=ellinit([1,0,1,-19,26]); ? ellorder(tcurve,[1,2]) 6 ? elltors(tcurve) [12, [6, 2], [[-2, 8], [3, -2]]] ? mcurve=ellinit([0,0,0,-17,0]) [0, 0, 0, -17, 0, 0, -34, 0, -289, 816, 0, 314432, 1728, [4.1231056256176605 498214098559740770251, 0.E-48, -4.1231056256176605498214098559740770251]~, 1 .2913084409290072207105564235857096010, -1.291308440929007220710556423585709 6010*I, 2.4328754881596176532948539893637583869, 2.4328754881596176532948539 893637583869*I, 1.6674774896145033307120230298772362382] ? 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, [2.000000000000 0000000000000000000000000, -0.62500000000000000000000000000000000000 + 0.330 71891388307382381270196920490755321*I, -0.6250000000000000000000000000000000 0000 - 0.33071891388307382381270196920490755321*I]~, 1.933311705616811546733 0768390298137311, -0.96665585280840577336653841951490686553 - 2.557530989916 0994790492257969408742850*I, 1.7116972661997117051282981581331545224 - 8.816 20763 E-39*I, -0.85584863309985585256414907906657726121 + 0.9855971481387316 4489992761459498878368*I, 4.9445046002825467364981969681843776445] ? ellpow(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))] ? \p96 realprecision = 96 significant digits ? precision(cmcurve) 38 ? getheap [57, 4700] ? print("Total time spent: ",gettime); Total time spent: 16 pari-2.5.5/src/test/32/bnfisintnorm0000644000175000017500000012166712147140047015546 0ustar billbill echo = 1 (on) ? setrand(1);bnf=bnfinit(x^2+105); ? for(i=1,1000,do(i)) 1: [1] 4: [2] 9: [3] 16: [4] 25: [5] 36: [6] 49: [7] 64: [8] 81: [9] 100: [10] 105: [x] 106: [x + 1, x - 1] 109: [x + 2, x - 2] 114: [x + 3, x - 3] 121: [x + 4, -11, x - 4] 130: [x + 5, x - 5] 141: [x + 6, x - 6] 144: [12] 154: [x - 7, -x - 7] 169: [x - 8, -13, x + 8] 186: [x + 9, x - 9] 196: [14] 205: [x + 10, x - 10] 225: [15] 226: [x + 11, x - 11] 249: [x + 12, x - 12] 256: [16] 274: [x + 13, x - 13] 289: [17] 301: [x + 14, x - 14] 324: [18] 330: [-x - 15, x - 15] 361: [x - 16, -19, x + 16] 394: [x + 17, x - 17] 400: [20] 420: [2*x] 421: [-2*x + 1, -2*x - 1] 424: [2*x + 2, 2*x - 2] 429: [-2*x + 3, -x + 18, -x - 18, -2*x - 3] 436: [2*x + 4, 2*x - 4] 441: [21] 445: [-2*x + 5, 2*x + 5] 456: [2*x + 6, 2*x - 6] 466: [x + 19, x - 19] 469: [-2*x + 7, 2*x + 7] 484: [2*x + 8, 22, 2*x - 8] 501: [-2*x + 9, 2*x + 9] 505: [x + 20, x - 20] 520: [2*x + 10, 2*x - 10] 529: [23] 541: [-2*x + 11, 2*x + 11] 546: [-x + 21, x + 21] 564: [2*x + 12, 2*x - 12] 576: [24] 589: [2*x - 13, -x - 22, x - 22, -2*x - 13] 616: [2*x - 14, -2*x - 14] 625: [25] 634: [x + 23, x - 23] 645: [2*x - 15, -2*x - 15] 676: [2*x - 16, -26, 2*x + 16] 681: [x + 24, x - 24] 709: [-2*x + 17, 2*x + 17] 729: [27] 730: [x + 25, x - 25] 744: [2*x + 18, 2*x - 18] 781: [x + 26, -2*x - 19, 2*x - 19, x - 26] 784: [28] 820: [2*x + 20, 2*x - 20] 834: [x + 27, x - 27] 841: [29] 861: [2*x - 21, -2*x - 21] 889: [x + 28, x - 28] 900: [30] 904: [2*x + 22, 2*x - 22] 945: [3*x] 946: [x - 29, -3*x - 1, -3*x + 1, x + 29] 949: [3*x + 2, -2*x - 23, 2*x - 23, -3*x + 2] 954: [3*x + 3, 3*x - 3] 961: [-3*x + 4, -31, 3*x + 4] 970: [-3*x - 5, 3*x - 5] 981: [3*x + 6, 3*x - 6] 994: [3*x + 7, 3*x - 7] 996: [2*x + 24, 2*x - 24] ? setrand(1);bnf=bnfinit(x^2-65); ? for(i=1,1000,do(i-500)) -491: [-6*x - 43, 6*x - 43] -490: [-13/2*x - 95/2, 7/2*x - 35/2, 37/2*x + 295/2, -53/2*x - 425/2, 7/2*x + 35/2, 157/2*x + 1265/2] -485: [3*x - 10, -3*x - 10] -484: [-11/2*x - 77/2, 22*x + 176, -11/2*x + 77/2] -481: [7*x + 52, 71*x + 572] -469: [-5*x + 34, -43*x - 346, 11*x + 86, 5*x + 34] -464: [99/2*x + 797/2, -15/2*x - 113/2, -3*x + 11, 15*x - 119, 4*x + 24, -4* x + 24, -15*x - 119, 3*x + 11, 127/2*x + 1023/2, -19/2*x - 147/2] -454: [73/2*x + 587/2, -7/2*x - 37/2, -7/2*x + 37/2, 25/2*x + 197/2] -446: [51/2*x + 409/2, 9/2*x + 59/2, -9/2*x + 59/2, -35/2*x - 279/2] -441: [-3*x + 12, 21*x + 168, 3*x + 12] -439: [-56*x - 451, -8*x - 61] -419: [30*x + 241, 14*x + 111] -416: [-279/2*x - 2249/2, 3*x + 13, -10*x - 78, 42*x + 338, -179*x - 1443, 7 /2*x + 39/2] -415: [4*x + 25, -4*x + 25] -406: [155/2*x + 1249/2, -23/2*x - 181/2, -17/2*x - 131/2, 5/2*x - 1/2, -5/2 *x - 1/2, 17/2*x - 131/2, 71/2*x + 571/2, -11/2*x - 79/2] -404: [5/2*x + 3/2, -33/2*x - 263/2, -6*x - 44, 6*x - 44, 49/2*x + 393/2, -5 /2*x + 3/2] -400: [5/2*x - 5/2, -5*x - 35, 20*x + 160, -85*x - 685, 5/2*x + 5/2] -394: [-125/2*x - 1007/2, 5/2*x + 7/2, 5/2*x - 7/2, -13/2*x - 97/2] -389: [-3*x + 14, 3*x + 14] -386: [185/2*x + 1491/2, 5/2*x - 9/2, -5/2*x - 9/2, -9/2*x - 61/2] -376: [5/2*x + 11/2, 7/2*x + 41/2, -7*x - 53, -13*x - 103, 29*x + 233, 7*x - 53, -247/2*x - 1991/2, -5/2*x + 11/2] -365: [9*x + 70, -41*x - 330] -364: [-437/2*x - 3523/2, 47/2*x + 377/2, 4*x + 26, -100*x - 806, -31/2*x - 247/2, 5/2*x + 13/2] -361: [19*x + 152] -360: [69/2*x + 555/2, 3*x - 15, 3*x + 15, 21/2*x + 165/2] -350: [5/2*x + 15/2, -95/2*x - 765/2, -15/2*x - 115/2, 5/2*x - 15/2] -335: [28*x + 225, -12*x - 95] -334: [5/2*x - 17/2, -215/2*x - 1733/2, -7/2*x - 43/2, 5/2*x + 17/2] -329: [3*x + 16, 5*x + 36, -69*x - 556, -3*x + 16] -326: [-11/2*x - 81/2, -29/2*x - 231/2, 45/2*x + 361/2, 11/2*x - 81/2] -324: [-9/2*x - 63/2, 18*x + 144, -9/2*x + 63/2] -316: [-19/2*x - 149/2, -5/2*x - 19/2, 40*x + 322, 8*x + 62, -5/2*x + 19/2, -19/2*x + 149/2] -315: [54*x + 435, 6*x + 45] -311: [-4*x + 27, 4*x + 27] -296: [-5/2*x + 21/2, -13/2*x - 99/2, 3*x + 17, 27*x + 217, -11*x - 87, -3*x + 17, 93/2*x + 749/2, 5/2*x + 21/2] -290: [43/2*x + 345/2, -7/2*x - 45/2, 183/2*x + 1475/2, -27/2*x - 215/2] -289: [17*x + 136] -274: [5/2*x + 23/2, -65/2*x - 523/2, -17/2*x - 133/2, 5/2*x - 23/2] -269: [7*x + 54, 39*x + 314] -261: [3*x + 18, -3*x + 18] -260: [121/2*x + 975/2, 2*x, 9/2*x + 65/2] -259: [-2*x + 1, -10*x - 79, 26*x + 209, 2*x + 1] -256: [25/2*x + 199/2, -5*x + 37, 2*x - 2, -4*x - 28, 16*x + 128, -4*x + 28, 2*x + 2, -5*x - 37, 41/2*x + 329/2] -251: [2*x - 3, -2*x - 3] -250: [5/2*x - 25/2, 5/2*x + 25/2] -244: [-151/2*x - 1217/2, 91/2*x + 733/2, 2*x + 4, -2*x + 4, -11/2*x - 83/2, 7/2*x + 47/2] -235: [2*x - 5, -2*x - 5] -234: [-15/2*x - 117/2, 63/2*x + 507/2] -225: [15*x + 120] -224: [39/2*x + 313/2, -5/2*x - 27/2, -3*x + 19, 9*x + 71, 2*x + 6, -38*x - 306, -6*x - 46, 2*x - 6, 25*x + 201, -3*x - 19, -5/2*x + 27/2, 23/2*x + 183/ 2] -211: [2*x - 7, -2*x - 7] -199: [-4*x - 29, 4*x - 29] -196: [61/2*x + 491/2, -7/2*x - 49/2, -181/2*x - 1459/2, -2*x + 8, 14*x + 11 2, 2*x + 8, 5/2*x + 29/2, -7/2*x + 49/2, -13/2*x - 101/2] -194: [-9/2*x - 67/2, -21/2*x - 167/2, 37/2*x + 297/2, 9/2*x - 67/2] -191: [24*x + 193, 8*x + 63] -185: [-3*x + 20, 3*x + 20] -181: [-5*x - 38, -37*x - 298] -179: [-2*x + 9, 2*x + 9] -169: [13*x + 104] -166: [35/2*x + 281/2, 5/2*x + 31/2, -5/2*x + 31/2, -19/2*x - 151/2] -160: [11/2*x + 85/2, 23*x + 185, 2*x - 10, 2*x + 10, 7*x + 55, 59/2*x + 475 /2] -146: [-87/2*x - 701/2, -3/2*x - 1/2, 3/2*x - 1/2, 7/2*x + 51/2] -144: [3/2*x - 3/2, -3*x - 21, 12*x + 96, -51*x - 411, 3/2*x + 3/2] -140: [-17/2*x - 135/2, 3/2*x + 5/2, 36*x + 290, 4*x + 30, -3/2*x + 5/2, 33/ 2*x + 265/2] -139: [2*x - 11, -2*x - 11] -134: [3/2*x - 7/2, 117/2*x + 943/2, -5/2*x - 33/2, -3/2*x - 7/2] -131: [22*x + 177, 6*x + 47] -126: [3/2*x + 9/2, -57/2*x - 459/2, -9/2*x - 69/2, 3/2*x - 9/2] -121: [11*x + 88] -116: [-211/2*x - 1701/2, 31/2*x + 249/2, 2*x + 12, -2*x + 12, -15/2*x - 119 /2, 3/2*x + 11/2] -104: [3/2*x + 13/2, -5*x - 39, 21*x + 169, -179/2*x - 1443/2] -101: [-3*x - 22, 3*x - 22] -100: [-5/2*x - 35/2, 10*x + 80, -5/2*x + 35/2] -94: [-7/2*x - 53/2, -13/2*x - 103/2, 29/2*x + 233/2, 7/2*x - 53/2] -91: [2*x + 13, -50*x - 403] -90: [3/2*x - 15/2, 3/2*x + 15/2] -81: [9*x + 72] -79: [20*x + 161, 4*x + 31] -74: [3/2*x + 17/2, 27/2*x + 217/2, -11/2*x - 87/2, -3/2*x + 17/2] -65: [x] -64: [-5/2*x + 37/2, x - 1, -2*x - 14, 8*x + 64, -34*x - 274, x + 1, -5/2*x - 37/2] -61: [x + 2, -x + 2] -56: [-3/2*x + 19/2, 9/2*x + 71/2, x + 3, -19*x - 153, -3*x - 23, x - 3, 25/ 2*x + 201/2, -3/2*x - 19/2] -49: [-x + 4, 7*x + 56, x + 4] -40: [23/2*x + 185/2, x - 5, x + 5, 7/2*x + 55/2] -36: [-3/2*x - 21/2, 6*x + 48, -3/2*x + 21/2] -35: [18*x + 145, 2*x + 15] -29: [x + 6, -x + 6] -26: [-5/2*x - 39/2, 21/2*x + 169/2] -25: [5*x + 40] -16: [1/2*x - 1/2, -x - 7, 4*x + 32, -17*x - 137, 1/2*x + 1/2] -14: [1/2*x + 3/2, -19/2*x - 153/2, -3/2*x - 23/2, 1/2*x - 3/2] -10: [1/2*x - 5/2, 1/2*x + 5/2] -9: [3*x + 24] -4: [-1/2*x - 7/2, 2*x + 16, -1/2*x + 7/2] -1: [x + 8] 0: [0] 1: [1] 4: [-15/2*x - 121/2, 2, -1/2*x - 9/2] 9: [3] 10: [3/2*x + 25/2, 13/2*x + 105/2] 14: [11/2*x + 89/2, -1/2*x - 11/2, 1/2*x - 11/2, 5/2*x + 41/2] 16: [7/2*x + 57/2, x - 9, 4, -x - 9, 9/2*x + 73/2] 25: [5] 26: [-79/2*x - 637/2, 1/2*x + 13/2] 29: [14*x + 113, -2*x - 17] 35: [x + 10, -x + 10] 36: [-45/2*x - 363/2, 6, -3/2*x - 27/2] 40: [1/2*x + 15/2, 3*x + 25, 13*x + 105, -1/2*x + 15/2] 49: [-4*x - 33, 7, 12*x + 97] 56: [-5/2*x - 43/2, -1/2*x + 17/2, 11*x + 89, -x - 11, x - 11, 5*x + 41, 1/2 *x + 17/2, -43/2*x - 347/2] 61: [10*x + 81, -6*x - 49] 64: [-3/2*x - 29/2, 7*x + 57, 2*x - 18, 8, -2*x - 18, 9*x + 73, -77/2*x - 62 1/2] 65: [8*x + 65] 74: [41/2*x + 331/2, 1/2*x + 19/2, 1/2*x - 19/2, -7/2*x - 59/2] 79: [x + 12, -x + 12] 81: [9] 90: [9/2*x + 75/2, 39/2*x + 315/2] 91: [29*x + 234, -3*x - 26] 94: [-109/2*x - 879/2, 1/2*x - 21/2, 1/2*x + 21/2, 3/2*x + 31/2] 100: [-75/2*x - 605/2, 10, -5/2*x - 45/2] 101: [-46*x - 371, 2*x + 19] 104: [37/2*x + 299/2, -79*x - 637, x + 13, -11/2*x - 91/2] 116: [-13/2*x - 107/2, 1/2*x + 23/2, 28*x + 226, -4*x - 34, 1/2*x - 23/2, -1 3/2*x + 107/2] 121: [11] 126: [33/2*x + 267/2, -3/2*x - 33/2, 3/2*x - 33/2, 15/2*x + 123/2] 131: [x + 14, -x + 14] 134: [17/2*x + 139/2, 7/2*x + 61/2, 7/2*x - 61/2, -31/2*x - 251/2] 139: [5*x + 42, -27*x - 218] 140: [1/2*x - 25/2, 29/2*x + 235/2, 2*x + 20, -2*x + 20, -19/2*x - 155/2, 1/ 2*x + 25/2] 144: [21/2*x + 171/2, 3*x - 27, 12, -3*x - 27, 27/2*x + 219/2] 146: [-5/2*x - 47/2, -25/2*x - 203/2, 23/2*x + 187/2, -5/2*x + 47/2] 160: [-3/2*x + 35/2, x + 15, 6*x + 50, 26*x + 210, -x + 15, 3/2*x + 35/2] 166: [1/2*x + 27/2, 71/2*x + 573/2, -9/2*x - 77/2, 1/2*x - 27/2] 169: [13] 179: [-7*x - 58, 25*x + 202] 181: [2*x - 21, -2*x - 21] 185: [-4*x - 35, 44*x + 355] 191: [x + 16, -x + 16] 194: [-139/2*x - 1121/2, 1/2*x - 29/2, 1/2*x + 29/2, 5/2*x + 49/2] 196: [3/2*x + 37/2, 7/2*x - 63/2, -11/2*x - 93/2, -8*x - 66, 14, 24*x + 194, -11/2*x + 93/2, -7/2*x - 63/2, 3/2*x - 37/2] 199: [-61*x - 492, 3*x + 28] 211: [9*x + 74, -23*x - 186] 224: [1/2*x + 31/2, -67/2*x - 541/2, -5*x - 43, -x + 17, 22*x + 178, -2*x - 22, 2*x - 22, 10*x + 82, x + 17, -43*x - 347, -13/2*x - 109/2, -1/2*x + 31/2 ] 225: [15] 234: [-237/2*x - 1911/2, 3/2*x + 39/2] 235: [11*x + 90, -21*x - 170] 244: [-9/2*x - 79/2, 5/2*x + 51/2, 20*x + 162, -12*x - 98, 5/2*x - 51/2, -9/ 2*x + 79/2] 250: [15/2*x + 125/2, 65/2*x + 525/2] 251: [13*x + 106, -19*x - 154] 256: [-1/2*x + 33/2, -3*x - 29, 14*x + 114, -60*x - 484, 16, -4*x - 36, 18*x + 146, -77*x - 621, 1/2*x + 33/2] 259: [-15*x - 122, x - 18, x + 18, 17*x + 138] 260: [7/2*x + 65/2, 16*x + 130, 137/2*x + 1105/2] 261: [42*x + 339, -6*x - 51] 269: [-2*x + 23, 2*x + 23] 274: [63/2*x + 509/2, -3/2*x - 41/2, 3/2*x - 41/2, 17/2*x + 141/2] 289: [17] 290: [1/2*x + 35/2, 11/2*x - 95/2, 11/2*x + 95/2, 1/2*x - 35/2] 296: [-19/2*x - 157/2, 5/2*x - 53/2, 41*x + 331, x + 19, x - 19, -7*x - 59, 5/2*x + 53/2, 61/2*x + 493/2] 311: [-5*x - 44, 59*x + 476] 315: [3*x + 30, -3*x + 30] 316: [-301/2*x - 2427/2, -59/2*x - 477/2, 2*x + 24, -2*x + 24, -21/2*x - 173 /2, -3/2*x - 43/2] 324: [-135/2*x - 1089/2, 18, -9/2*x - 81/2] 326: [-169/2*x - 1363/2, 1/2*x - 37/2, 1/2*x + 37/2, 7/2*x + 67/2] 329: [40*x + 323, -4*x + 37, -4*x - 37, -8*x - 67] 334: [23/2*x + 189/2, -13/2*x - 111/2, 13/2*x - 111/2, 57/2*x + 461/2] 335: [x + 20, x - 20] 350: [55/2*x + 445/2, -5/2*x - 55/2, 5/2*x - 55/2, 25/2*x + 205/2] 360: [3/2*x + 45/2, 9*x + 75, 39*x + 315, -3/2*x + 45/2] 361: [19] 364: [-27/2*x - 221/2, 1/2*x + 39/2, 58*x + 468, -6*x - 52, -495/2*x - 3991/ 2, 53/2*x + 429/2] 365: [-2*x + 25, -2*x - 25] 376: [51/2*x + 413/2, -15/2*x + 127/2, -109*x - 879, x - 21, x + 21, 3*x + 3 1, -15/2*x - 127/2, -29/2*x - 237/2] 386: [11/2*x + 97/2, 31/2*x + 253/2, -49/2*x - 397/2, 11/2*x - 97/2] 389: [-10*x - 83, 38*x + 307] 394: [-7/2*x - 69/2, 47/2*x + 381/2, 33/2*x + 269/2, 7/2*x - 69/2] 400: [35/2*x + 285/2, 5*x - 45, 20, -5*x - 45, 45/2*x + 365/2] 404: [43/2*x + 349/2, 1/2*x - 41/2, -92*x - 742, 4*x + 38, 1/2*x + 41/2, -37 /2*x - 301/2] 406: [9/2*x + 83/2, 3/2*x - 47/2, -267/2*x - 2153/2, 39/2*x + 317/2, -41/2*x - 333/2, 5/2*x + 57/2, 3/2*x + 47/2, 9/2*x - 83/2] 415: [57*x + 460, -7*x - 60] 416: [-17/2*x - 143/2, 37*x + 299, -158*x - 1274, 2*x + 26, -11*x - 91, 95/2 *x + 767/2] 419: [x + 22, -x + 22] 439: [-3*x - 32, 3*x - 32] 441: [-12*x - 99, 21, 36*x + 291] 446: [1/2*x + 43/2, 131/2*x + 1057/2, -13/2*x - 113/2, 1/2*x - 43/2] 454: [3/2*x + 49/2, -93/2*x - 751/2, -19/2*x - 159/2, -3/2*x + 49/2] 464: [5/2*x + 59/2, 7/2*x - 71/2, -13*x - 107, x + 23, 56*x + 452, -8*x - 68 , -239*x - 1927, 35*x + 283, 7/2*x + 71/2, 5/2*x - 59/2] 469: [-6*x - 53, -2*x - 27, -2*x + 27, 74*x + 597] 481: [108*x + 871, 4*x + 39] 484: [-165/2*x - 1331/2, 22, -11/2*x - 99/2] 485: [14*x + 115, -34*x - 275] 490: [9/2*x - 85/2, 21/2*x + 175/2, -1/2*x + 45/2, -1/2*x - 45/2, 91/2*x + 7 35/2, 9/2*x + 85/2] 491: [-91*x - 734, 5*x + 46] ? setrand(1);bnf=bnfinit(x^5-37); ? for(i=1,1000,do(i-500)) -499: [-2374*x^4 + 1671*x^3 + 4497*x^2 - 22065*x + 54444] -497: [-3457*x^4 + 2824*x^3 + 15097*x^2 + 751*x - 76402, -10*x^4 - 5*x^3 + 9 *x^2 - 23*x - 182, -x^3 + 2*x^2 - 5*x + 3] -496: [-33*x^4 + 31*x^3 + 177*x^2 + 89*x - 647, 306*x^4 + 1960*x^3 + 1005*x^ 2 - 7425*x - 14522] -494: [-6*x^4 + 14*x^3 - 21*x^2 + 11*x + 52] -491: [1888*x^4 + 8569*x^3 + 2900*x^2 - 32636*x - 53824, 6486*x^4 - 17022*x^ 3 + 29212*x^2 - 25158*x - 40023, -1027*x^4 - 866*x^3 + 3228*x^2 + 7730*x - 3 948] -490: [-2*x^4 + 3*x^3 - 2*x^2 - 7*x + 30] -487: [-5668*x^4 + 14258*x^3 - 23472*x^2 + 17752*x + 40361] -486: [-528345*x^4 + 15834*x^3 + 2186994*x^2 - 7352895*x + 15224466] -483: [21*x^4 + 4*x^3 - 84*x^2 - 124*x + 198] -481: [-6*x^4 + 20*x^3 - 41*x^2 + 52*x] -478: [x^3 + x^2 - 3*x - 9] -477: [-3*x^4 - 6*x^3 - 12*x^2 - 25*x - 53] -476: [-149520*x^4 + 433375*x^3 + 1184038*x^2 - 333085*x - 5448548] -475: [28292*x^4 + 18315*x^3 - 96637*x^2 - 200626*x + 154333] -474: [-38962*x^4 - 243483*x^3 + 976308*x^2 - 2220316*x + 3258047] -468: [-6*x^4 + 26*x^3 - 61*x^2 + 93*x - 52] -466: [-1159032*x^4 - 2381161*x^3 - 4715244*x^2 - 9491919*x - 20062122] -465: [-2*x^4 - 4*x^3 - 9*x^2 - 20*x - 40, -x^2 + x - 3, -4609*x^4 - 1282*x^ 3 + 17907*x^2 + 28221*x - 40000, 4156*x^4 + 116355*x^3 + 130442*x^2 - 327263 *x - 969403] -463: [11*x^4 - 5*x^3 - 30*x^2 + 121*x - 276] -461: [x^4 - 2*x^3 + 3*x^2 - 4*x - 5] -457: [87*x^4 + 185*x^3 - 134*x^2 - 956*x - 651] -455: [-2*x^4 - 4*x^3 - 6*x^2 - 10*x - 27] -454: [-42409*x^4 - 90034*x^3 + 479719*x^2 - 1216471*x + 2018953] -452: [17*x^4 - 280*x^3 + 858*x^2 - 1677*x + 1938] -450: [14171*x^4 - 24148*x^3 - 90804*x^2 - 13185*x + 368144] -448: [-4174*x^4 - 4308*x^3 + 32046*x^2 - 88496*x + 158968, -48*x^4 + 86*x^3 - 83*x^2 - 88*x + 645] -447: [-3023*x^4 + 8573*x^3 + 23724*x^2 - 6154*x - 108401] -446: [-3334966*x^4 + 10447057*x^3 - 20665939*x^2 + 24559864*x + 5787442] -443: [52874*x^4 + 359697*x^3 + 233432*x^2 - 1228056*x - 2552814] -442: [-72646*x^4 + 242032*x^3 - 498349*x^2 + 634190*x - 161] -441: [x^3 + x^2 - 2*x - 9] -439: [-340*x^4 + 658*x^3 - 751*x^2 - 288*x + 4142] -435: [-2*x^3 - 5*x^2 - 3*x + 7] -434: [-229020*x^4 + 2937*x^3 + 961070*x^2 - 3214168*x + 6633571] -426: [307*x^4 - 457*x^3 + 221*x^2 + 1201*x - 4938, -75*x^4 + 4*x^3 + 323*x^ 2 + 394*x - 868] -425: [-6*x^4 - 12*x^3 - 21*x^2 - 40*x - 94] -424: [-453*x^4 - 931*x^3 - 1907*x^2 - 3921*x - 8108] -419: [-560*x^4 - 1235*x^3 - 2463*x^2 - 4622*x - 9283] -417: [35136*x^4 + 13626*x^3 - 131611*x^2 - 225241*x + 271295] -416: [-12*x^3 + 40*x^2 - 82*x + 104, x^3 + x^2 - 3*x - 7] -415: [-7002*x^4 + 19830*x^3 + 54916*x^2 - 14183*x - 250846] -412: [-533623*x^4 - 713164*x^3 + 4637959*x^2 - 12427717*x + 21740721] -405: [-1011048403*x^4 + 1415314931*x^3 - 428988586*x^2 - 4570622078*x + 170 45167535] -403: [-78*x^4 - 316*x^3 + 1381*x^2 - 3266*x + 5016] -402: [233347*x^4 + 322792*x^3 - 588962*x^2 - 2139460*x - 270287] -400: [14121*x^4 + 42463*x^3 - 5833*x^2 - 187441*x - 213811, 485552*x^4 - 40 941*x^3 - 2110863*x^2 - 2513370*x + 5748258] -398: [441717*x^4 + 4114047*x^3 - 15578087*x^2 + 34456844*x - 48751711] -394: [-679*x^4 - 1411*x^3 - 2866*x^2 - 5796*x - 11966] -392: [-6*x^4 + 15*x^3 + 43*x^2 - 12*x - 204] -386: [-730*x^4 - 1503*x^3 - 3089*x^2 - 6353*x - 13095] -382: [-51*x^4 + 127*x^3 - 207*x^2 + 151*x + 374, -294*x^4 + 873*x^3 - 1662* x^2 + 1836*x + 929, 289473*x^4 - 50508*x^3 - 1294621*x^2 - 1439915*x + 36421 73] -381: [-57727*x^4 - 148801*x^3 - 285231*x^2 - 433426*x - 786240] -380: [1075950*x^4 - 3190519*x^3 + 6067791*x^2 - 6689147*x - 3438103] -373: [7*x^4 + 5*x^3 - 47*x^2 + 134*x - 250] -372: [151*x^4 - 1096*x^3 - 2144*x^2 + 1693*x + 10780, -88*x^4 - 81*x^3 + 26 7*x^2 + 677*x - 283, 779081*x^4 - 5131030*x^3 + 13790905*x^2 - 24191847*x + 22130971, -52905*x^4 - 2341*x^3 + 232072*x^2 - 763203*x + 1558749] -371: [34641*x^4 - 160448*x^3 - 351019*x^2 + 233495*x + 1785138] -370: [718442*x^4 - 3908961*x^3 + 9976752*x^2 - 16665899*x + 13227796] -365: [-119204*x^4 + 250756*x^3 - 330045*x^2 + 36518*x + 1277460] -364: [155*x^4 + 3056*x^3 + 3149*x^2 - 9118*x - 25302] -361: [112*x^4 - 244*x^3 + 335*x^2 - 88*x - 1140] -360: [360934*x^4 - 4627403*x^3 + 13885713*x^2 - 26642651*x + 29893695] -359: [-3*x^3 + 10*x^2 - 21*x + 27] -358: [-67*x^4 - 301*x^3 - 99*x^2 + 1150*x + 1883] -355: [-119*x^4 - 176*x^3 - 403*x^2 - 1174*x - 2683, -x^4 - 2*x^3 - 4*x^2 - 9*x - 19, 20559*x^4 - 26813*x^3 + 2172*x^2 + 106429*x - 363766] -354: [-x^4 - x^3 + 3*x^2 + 8*x - 3] -350: [435*x^4 - 622*x^3 + 228*x^2 + 1877*x - 7220] -349: [94370*x^4 + 184667*x^3 - 165066*x^2 - 992882*x - 563692] -348: [-2750*x^4 - 1189*x^3 + 10123*x^2 + 17877*x - 20257] -347: [-393095*x^4 + 806794*x^3 - 1021365*x^2 - 17551*x + 4388208] -345: [-x^2 + 4] -343: [-19831*x^4 + 47808*x^3 + 135700*x^2 - 48936*x - 676534] -342: [131*x^4 - 487*x^3 + 1066*x^2 - 1489*x + 437] -340: [461*x^4 + 5016*x^3 + 4154*x^2 - 16543*x - 39824] -338: [139953*x^4 + 382867*x^3 - 110583*x^2 - 1773000*x - 1806375] -337: [-31398*x^4 + 57827*x^3 - 59544*x^2 - 46773*x + 408237] -333: [36*x^4 - 523*x^3 + 1589*x^2 - 3078*x + 3515] -332: [34628262*x^4 - 27740099*x^3 - 54381419*x^2 + 298761718*x - 764765542] -327: [-1312*x^4 - 2690*x^3 - 5512*x^2 - 11363*x - 23526] -326: [-213271*x^4 - 448404*x^3 - 949328*x^2 - 1948400*x - 3893091] -325: [-x^3 - 2*x^2 - 14] -324: [-59*x^4 - 559*x^3 + 2112*x^2 - 4667*x + 6593] -323: [402698*x^4 - 158391*x^3 - 1908700*x^2 - 1757439*x + 5854795] -321: [-4360*x^4 - 9021*x^3 - 18634*x^2 - 38256*x - 78370] -320: [715016*x^4 + 1436884*x^3 - 7817922*x^2 + 19953504*x - 33331798, 10818 *x^4 - 18021*x^3 + 14176*x^2 + 29168*x - 157265] -317: [-26*x^4 + 70*x^3 - 123*x^2 + 113*x + 145] -315: [-15*x^3 + 50*x^2 - 103*x + 131] -314: [-20*x^4 - 42*x^3 - 86*x^2 - 173*x - 353] -313: [11471*x^4 - 91948*x^3 - 165652*x^2 + 178948*x + 929842] -310: [-20259*x^4 - 49809*x^3 - 229335*x^2 - 599186*x - 857837] -306: [72981*x^4 - 634070*x^3 - 1116239*x^2 + 1267500*x + 6344734] -304: [-19*x^4 + 243*x^3 - 731*x^2 + 1401*x - 1577, 62*x^4 - 259*x^3 + 600*x ^2 - 901*x + 458] -296: [2*x^4 - 261*x^3 + 861*x^2 - 1762*x + 2220] -293: [173123*x^4 - 1161964*x^3 + 3137080*x^2 - 5525136*x + 5107878] -292: [-x^4 - 2*x^3 - 4*x^2 - 9*x - 16] -291: [68488791*x^4 - 28662621*x^3 - 194848612*x^2 + 770626148*x - 174127494 7] -289: [-42*x^4 - 68*x^3 - 84*x^2 - 180*x - 617] -288: [190*x^4 + 72*x^3 - 1046*x^2 + 3178*x - 6156, -58*x^4 - 263*x^3 + 1122 *x^2 - 2623*x + 3982] -284: [93394*x^4 - 60075*x^3 - 478379*x^2 - 366460*x + 1536088, 157*x^4 - 58 *x^3 - 791*x^2 - 867*x + 2031, -x^2 - 3*x - 4] -282: [-196079*x^4 - 9567*x^3 + 816242*x^2 + 1073455*x - 2106085] -281: [11*x^4 - 26*x^3 + 40*x^2 - 23*x - 93, -77986*x^4 - 198610*x^3 - 51456 6*x^2 - 1032612*x - 1644077, 46143*x^4 - 67240*x^3 + 28396*x^2 + 190443*x - 754819] -280: [-x - 3] -279: [1826756*x^4 - 4986049*x^3 + 8866643*x^2 - 8401714*x - 9597647] -276: [-581*x^4 - 370*x^3 + 1992*x^2 + 4103*x - 3224] -274: [-x^4 - 2*x^3 - 4*x^2 - 9*x - 18] -272: [329717*x^4 + 475679*x^3 - 792461*x^2 - 3024939*x - 489939, 19260*x^4 - 3158851*x^3 + 10441779*x^2 - 21394937*x + 27010829] -269: [-x^3 - 2*x^2 + 3*x + 11] -267: [8229*x^4 - 28696*x^3 + 60714*x^2 - 80616*x + 11188] -266: [15*x^4 - 5*x^3 - 70*x^2 - 68*x + 210] -265: [-279*x^4 - 1656*x^3 - 925*x^2 + 5842*x + 11353] -260: [6*x^4 + 16*x^3 - 23*x^2 - 134*x - 149] -259: [9*x^4 - 14*x^3 - 56*x^2 - 12*x + 222] -258: [x^4 - 3*x^3 - 8*x^2 + 2*x + 38] -256: [-209*x^4 + 171*x^3 + 315*x^2 - 1777*x + 4579, 120*x^4 + 4*x^3 - 522*x ^2 + 1722*x - 3524, x^4 - 2*x^3 + 2*x^2 - 9] -252: [3*x^4 - 23*x^3 - 42*x^2 + 44*x + 234] -250: [-95029*x^4 + 123210*x^3 - 7619*x^2 - 496926*x + 1687762] -248: [5798*x^4 - 3231*x^3 - 13815*x^2 + 59720*x - 140388] -247: [1023*x^4 - 3286*x^3 - 8521*x^2 + 3081*x + 40030] -245: [-284*x^4 - 92*x^3 - 909*x^2 - 4876*x - 10812] -243: [-3] -239: [6315*x^4 - 83245*x^3 - 134364*x^2 + 178484*x + 789649] -238: [-x^4 - 10*x^3 + 37*x^2 - 82*x + 114] -237: [-x^4 - 2*x^3 - 4*x^2 - 8*x - 18] -234: [-700*x^4 - 3609*x^3 - 1626*x^2 + 13228*x + 23721] -233: [-170*x^4 + 349*x^3 - 442*x^2 - 7*x + 1897] -227: [x^4 + x^3 - 3*x^2 - 8*x + 2] -226: [-2057*x^4 - 4233*x^3 - 8717*x^2 - 17959*x - 36984] -225: [-287*x^4 + 3825*x^3 - 11526*x^2 + 22183*x - 25040] -224: [12*x^4 + 18*x^3 - 28*x^2 - 112*x - 24, 209*x^4 - 305*x^3 - 1277*x^2 - 338*x + 4971] -223: [-x^3 + x^2 - 4*x - 1] -221: [-2*x^4 - 4*x^3 - 8*x^2 - 17*x - 36] -217: [3*x^4 - 10*x^3 + 20*x^2 - 24*x - 2] -213: [-15*x^4 - 40*x^3 - 116*x^2 - 243*x - 363, -5266075*x^4 + 2073982*x^3 + 15414497*x^2 - 60143957*x + 135019482] -212: [-115365677*x^4 + 45854629*x^3 + 336294021*x^2 - 1314718510*x + 295425 8329] -208: [1723*x^4 + 323*x^3 - 6895*x^2 - 10147*x + 16309, 4616*x^4 - 77366*x^3 - 118173*x^2 + 177269*x + 725858] -206: [x - 3] -201: [-x^4 + 5*x^3 - 17*x^2 + 26*x - 34] -200: [-9*x^4 + 15*x^3 - 12*x^2 - 24*x + 130] -199: [-2*x^4 - 4*x^3 - 7*x^2 - 19*x - 29] -197: [22383064*x^4 - 43634035*x^3 + 50477245*x^2 + 16811671*x - 269988108] -196: [-6793545*x^4 + 10693841*x^3 - 6826578*x^2 - 22590870*x + 104198448] -193: [151377130*x^4 - 431708160*x^3 + 796483374*x^2 - 823328390*x - 6335835 09] -191: [-99*x^4 - 176*x^3 - 284*x^2 - 603*x - 1597, -55*x^4 - 112*x^3 + 90*x^ 2 + 588*x + 364, -3*x^4 + 10*x^3 - 22*x^2 + 28*x - 6] -190: [-x^2 + x + 2] -186: [11602*x^4 - 9070*x^3 - 18967*x^2 + 101636*x - 258187, 142431*x^4 + 48 0237*x^3 - 2203655*x^2 + 5305471*x - 8333030, -4*x^4 - 8*x^3 - 18*x^2 - 33*x - 75, x^4 - 2*x^3 + 4*x^2 - 8*x - 1] -185: [-x^2 + 2*x] -182: [-5804*x^4 + 5839*x^3 + 5152*x^2 - 41916*x + 117799] -180: [-x^2 + 3*x - 2] -179: [5089960*x^4 - 2068704*x^3 - 14685499*x^2 + 57692992*x - 129944660] -177: [82854*x^4 + 117450*x^3 - 202163*x^2 - 755931*x - 106537] -175: [-72*x^4 - 148*x^3 - 316*x^2 - 666*x - 1343] -174: [-41*x^4 - 8383*x^3 + 28101*x^2 - 58079*x + 74360] -171: [-802*x^4 - 1651*x^3 - 3405*x^2 - 7019*x - 14438] -170: [-6*x^4 + 2608*x^3 - 8663*x^2 + 17804*x - 22589] -169: [-4*x^4 + 15*x^2 - 54*x + 108] -166: [-3*x^4 + 4*x^3 - 17*x + 54] -163: [2245*x^4 - 3153*x^3 + 987*x^2 + 10078*x - 37758] -162: [-277*x^4 - 572*x^3 - 1182*x^2 - 2432*x - 4987] -160: [-2*x + 4, -5*x^3 - 7*x^2 + 11*x + 41] -157: [-241448*x^4 - 417679*x^3 - 864708*x^2 - 2123175*x - 4787585] -155: [-772*x^4 + 2268*x^3 - 4283*x^2 + 4654*x + 2652] -153: [59*x^4 - 112*x^3 + 123*x^2 + 65*x - 738] -152: [-439*x^4 - 73*x^3 + 1768*x^2 + 2559*x - 4239] -148: [-297*x^4 + 224*x^3 + 1544*x^2 + 1015*x - 5254] -146: [-12135*x^4 - 22239*x^3 - 42377*x^2 - 94551*x - 218424] -144: [-525*x^4 - 1079*x^3 - 2223*x^2 - 4587*x - 9451, -155*x^4 + 521*x^3 + 1320*x^2 - 529*x - 6269] -142: [3*x^4 + 5*x^3 - 32*x^2 + 80*x - 142, 42124*x^4 - 125551*x^3 + 239691* x^2 - 266277*x - 129013, -13516*x^4 - 35437*x^3 + 1336*x^2 + 129548*x + 1131 15] -141: [6*x^4 - 5*x^3 - 10*x^2 + 52*x - 136] -140: [-391*x^4 - 16914*x^3 - 23679*x^2 + 33718*x + 127118] -138: [-346952*x^4 + 739554*x^3 - 992969*x^2 + 172892*x + 3633389] -137: [-10436*x^4 - 28118*x^3 - 58568*x^2 - 93336*x - 154633] -136: [-x^2 + x - 4] -133: [11850914*x^4 - 39486071*x^3 + 81306239*x^2 - 103476243*x + 50856] -130: [148905438*x^4 - 497156819*x^3 + 1024997560*x^2 - 1307154759*x + 95299 62] -129: [-121239*x^4 + 197007*x^3 + 764634*x^2 + 137825*x - 3066062] -128: [-284*x^4 - 594*x^3 + 448*x^2 + 3088*x + 2030, -6844*x^4 + 4689*x^3 + 34974*x^2 + 24615*x - 116962] -126: [-579103*x^4 - 50757882*x^3 + 171550192*x^2 - 356332674*x + 459859773] -125: [-16*x^4 - 33*x^3 - 68*x^2 - 140*x - 288] -124: [-63*x^4 - 130*x^3 - 268*x^2 - 551*x - 1132] -119: [-378*x^4 - 819*x^3 - 1878*x^2 - 3938*x - 7386] -117: [16530*x^4 - 73563*x^3 + 174995*x^2 - 271134*x + 161425] -113: [101777454*x^4 - 158642204*x^3 + 97050316*x^2 + 349196731*x - 15747298 66] -112: [12430017*x^4 + 11271811*x^3 - 90243953*x^2 + 252856431*x - 459808917, 137153*x^4 - 248761*x^3 + 247310*x^2 + 230649*x - 1816775] -106: [11*x^4 - 11*x^3 - 10*x^2 + 80*x - 224] -104: [128*x^4 - 165*x^3 + 7*x^2 + 676*x - 2282] -103: [5488*x^4 - 723*x^3 - 24894*x^2 - 30073*x + 64255] -100: [-182*x^4 - 416*x^3 - 585*x^2 - 684*x - 1897] -98: [-2*x^3 - x^2 - 4*x - 15] -95: [-6855*x^4 + 14582*x^3 + 47479*x^2 - 1679*x - 203984] -93: [-36*x^4 - 74*x^3 - 152*x^2 - 313*x - 646, -x^4 - 2*x^3 - 4*x^2 - 9*x - 17, 814*x^4 - 2981*x^3 - 7244*x^2 + 3419*x + 35059, -20965*x^4 - 37774*x^3 + 40807*x^2 + 212056*x + 96849] -91: [-27*x^4 - 56*x^3 - 116*x^2 - 238*x - 486] -90: [2422*x^4 + 19015*x^3 + 13882*x^2 - 63040*x - 139265] -87: [-7*x^4 - 14*x^3 - 30*x^2 - 65*x - 133] -85: [2*x^4 + 10*x^3 + 4*x^2 - 37*x - 64] -83: [-2588*x^4 - 12178*x^3 - 4526*x^2 + 45864*x + 77545] -81: [266742807*x^4 - 477562789*x^3 + 460189353*x^2 + 491390120*x - 35878418 38] -80: [-9277*x^4 - 4433*x^3 + 33597*x^2 + 61361*x - 64719, -56126*x^4 + 37330 0*x^3 + 705659*x^2 - 699545*x - 3912460] -76: [-170837*x^4 + 734276*x^3 - 1721967*x^2 + 2623857*x - 1441433] -74: [5278*x^4 + 728998*x^3 - 2450965*x^2 + 5074822*x - 6516255] -73: [25820*x^4 - 67564*x^3 + 115628*x^2 - 98789*x - 161060] -72: [181393*x^4 + 723720*x^3 - 3179963*x^2 + 7525787*x - 11591077] -71: [-1991*x^4 - 4101*x^3 - 8378*x^2 - 17159*x - 35492, -17*x^4 - 35*x^3 - 72*x^2 - 148*x - 305, -5556*x^4 + 9447*x^3 - 7919*x^2 - 13666*x + 79097] -70: [2020*x^4 + 20331*x^3 - 76294*x^2 + 167980*x - 236187] -69: [-x - 2] -68: [-1758*x^4 - 3055*x^3 - 1094*x^2 + 1966*x - 12611] -65: [-6*x^4 + 32*x^3 - 81*x^2 + 134*x - 104] -64: [-352230*x^4 + 10556*x^3 + 1457996*x^2 - 4901930*x + 10149644, -2661*x^ 4 + 5496*x^3 - 7029*x^2 + 118*x + 29404] -63: [x^4 + 2*x^3 - 11*x^2 + 28*x - 47] -62: [-739233*x^4 - 1498725*x^3 - 3047259*x^2 - 6323853*x - 13246892] -56: [-x^4 - 2*x^3 - 4*x^2 - 8*x - 17] -53: [325*x^4 + 371*x^3 - 914*x^2 - 2753*x + 336] -52: [-57*x^4 - 108*x^3 - 200*x^2 - 423*x - 980] -50: [25730*x^4 - 43569*x^3 + 36072*x^2 + 64525*x - 367876] -49: [-5896*x^4 - 12076*x^3 - 24244*x^2 - 49397*x - 103670] -45: [-154*x^4 - 595*x^3 + 2635*x^2 - 6256*x + 9671] -40: [-118*x^4 - 265*x^3 + 1383*x^2 - 3484*x + 5744] -38: [-x - 1] -37: [-x] -36: [-x + 1] -35: [-3*x^4 - 32*x^3 - 28*x^2 + 100*x + 246] -34: [-173*x^4 - 352*x^3 + 1904*x^2 - 4855*x + 8094] -32: [-2, -x^4 - 2*x^3 - 9*x^2 - 25*x - 39] -31: [124*x^4 - 524*x^3 + 1220*x^2 - 1843*x + 968] -28: [-8346*x^4 - 17083*x^3 - 51080*x^2 - 125839*x - 217960] -26: [-19911372*x^4 + 109082694*x^3 - 278991431*x^2 + 467014698*x - 37312536 3] -25: [-x^2 + 4*x - 4] -20: [-13*x^4 + 818*x^3 + 1096*x^2 - 2073*x - 7284] -19: [-2090*x^4 - 11035*x^3 - 7488*x^2 + 32503*x + 63327] -18: [-3789*x^4 - 5156*x^3 + 8703*x^2 + 31288*x - 464] -17: [-2*x^4 - 2*x^3 + 6*x^2 + 16*x - 5] -16: [1699*x^4 - 5879*x^3 - 16191*x^2 + 1215*x + 63791, -80106*x^4 - 216338* x^3 - 59376*x^2 + 586907*x + 474269] -14: [-2087*x^4 - 2154*x^3 + 16023*x^2 - 44248*x + 79484] -13: [-6*x^3 + 20*x^2 - 41*x + 52] -10: [357508*x^4 + 718442*x^3 - 3908961*x^2 + 9976752*x - 16665899] -9: [95*x^4 + 36*x^3 - 523*x^2 + 1589*x - 3078] -8: [60*x^4 + 2*x^3 - 261*x^2 + 861*x - 1762] -7: [6*x^4 + 9*x^3 - 14*x^2 - 56*x - 12] -5: [-x + 2] -4: [-142*x^4 - 297*x^3 + 224*x^2 + 1544*x + 1015] -2: [-176115*x^4 + 5278*x^3 + 728998*x^2 - 2450965*x + 5074822] -1: [-1] 0: [0] 1: [1] 2: [176115*x^4 - 5278*x^3 - 728998*x^2 + 2450965*x - 5074822] 4: [142*x^4 + 297*x^3 - 224*x^2 - 1544*x - 1015] 5: [x - 2] 7: [-6*x^4 - 9*x^3 + 14*x^2 + 56*x + 12] 8: [-60*x^4 - 2*x^3 + 261*x^2 - 861*x + 1762] 9: [-95*x^4 - 36*x^3 + 523*x^2 - 1589*x + 3078] 10: [-357508*x^4 - 718442*x^3 + 3908961*x^2 - 9976752*x + 16665899] 13: [6*x^3 - 20*x^2 + 41*x - 52] 14: [2087*x^4 + 2154*x^3 - 16023*x^2 + 44248*x - 79484] 16: [-1699*x^4 + 5879*x^3 + 16191*x^2 - 1215*x - 63791, 80106*x^4 + 216338*x ^3 + 59376*x^2 - 586907*x - 474269] 17: [2*x^4 + 2*x^3 - 6*x^2 - 16*x + 5] 18: [3789*x^4 + 5156*x^3 - 8703*x^2 - 31288*x + 464] 19: [2090*x^4 + 11035*x^3 + 7488*x^2 - 32503*x - 63327] 20: [13*x^4 - 818*x^3 - 1096*x^2 + 2073*x + 7284] 25: [x^2 - 4*x + 4] 26: [19911372*x^4 - 109082694*x^3 + 278991431*x^2 - 467014698*x + 373125363] 28: [8346*x^4 + 17083*x^3 + 51080*x^2 + 125839*x + 217960] 31: [-124*x^4 + 524*x^3 - 1220*x^2 + 1843*x - 968] 32: [2, x^4 + 2*x^3 + 9*x^2 + 25*x + 39] 34: [173*x^4 + 352*x^3 - 1904*x^2 + 4855*x - 8094] 35: [3*x^4 + 32*x^3 + 28*x^2 - 100*x - 246] 36: [x - 1] 37: [x] 38: [x + 1] 40: [118*x^4 + 265*x^3 - 1383*x^2 + 3484*x - 5744] 45: [154*x^4 + 595*x^3 - 2635*x^2 + 6256*x - 9671] 49: [5896*x^4 + 12076*x^3 + 24244*x^2 + 49397*x + 103670] 50: [-25730*x^4 + 43569*x^3 - 36072*x^2 - 64525*x + 367876] 52: [57*x^4 + 108*x^3 + 200*x^2 + 423*x + 980] 53: [-325*x^4 - 371*x^3 + 914*x^2 + 2753*x - 336] 56: [x^4 + 2*x^3 + 4*x^2 + 8*x + 17] 62: [739233*x^4 + 1498725*x^3 + 3047259*x^2 + 6323853*x + 13246892] 63: [-x^4 - 2*x^3 + 11*x^2 - 28*x + 47] 64: [352230*x^4 - 10556*x^3 - 1457996*x^2 + 4901930*x - 10149644, 2661*x^4 - 5496*x^3 + 7029*x^2 - 118*x - 29404] 65: [6*x^4 - 32*x^3 + 81*x^2 - 134*x + 104] 68: [1758*x^4 + 3055*x^3 + 1094*x^2 - 1966*x + 12611] 69: [x + 2] 70: [-2020*x^4 - 20331*x^3 + 76294*x^2 - 167980*x + 236187] 71: [1991*x^4 + 4101*x^3 + 8378*x^2 + 17159*x + 35492, 17*x^4 + 35*x^3 + 72* x^2 + 148*x + 305, 5556*x^4 - 9447*x^3 + 7919*x^2 + 13666*x - 79097] 72: [-181393*x^4 - 723720*x^3 + 3179963*x^2 - 7525787*x + 11591077] 73: [-25820*x^4 + 67564*x^3 - 115628*x^2 + 98789*x + 161060] 74: [-5278*x^4 - 728998*x^3 + 2450965*x^2 - 5074822*x + 6516255] 76: [170837*x^4 - 734276*x^3 + 1721967*x^2 - 2623857*x + 1441433] 80: [9277*x^4 + 4433*x^3 - 33597*x^2 - 61361*x + 64719, 56126*x^4 - 373300*x ^3 - 705659*x^2 + 699545*x + 3912460] 81: [-266742807*x^4 + 477562789*x^3 - 460189353*x^2 - 491390120*x + 35878418 38] 83: [2588*x^4 + 12178*x^3 + 4526*x^2 - 45864*x - 77545] 85: [-2*x^4 - 10*x^3 - 4*x^2 + 37*x + 64] 87: [7*x^4 + 14*x^3 + 30*x^2 + 65*x + 133] 90: [-2422*x^4 - 19015*x^3 - 13882*x^2 + 63040*x + 139265] 91: [27*x^4 + 56*x^3 + 116*x^2 + 238*x + 486] 93: [36*x^4 + 74*x^3 + 152*x^2 + 313*x + 646, x^4 + 2*x^3 + 4*x^2 + 9*x + 17 , -814*x^4 + 2981*x^3 + 7244*x^2 - 3419*x - 35059, 20965*x^4 + 37774*x^3 - 4 0807*x^2 - 212056*x - 96849] 95: [6855*x^4 - 14582*x^3 - 47479*x^2 + 1679*x + 203984] 98: [2*x^3 + x^2 + 4*x + 15] 100: [182*x^4 + 416*x^3 + 585*x^2 + 684*x + 1897] 103: [-5488*x^4 + 723*x^3 + 24894*x^2 + 30073*x - 64255] 104: [-128*x^4 + 165*x^3 - 7*x^2 - 676*x + 2282] 106: [-11*x^4 + 11*x^3 + 10*x^2 - 80*x + 224] 112: [-12430017*x^4 - 11271811*x^3 + 90243953*x^2 - 252856431*x + 459808917, -137153*x^4 + 248761*x^3 - 247310*x^2 - 230649*x + 1816775] 113: [-101777454*x^4 + 158642204*x^3 - 97050316*x^2 - 349196731*x + 15747298 66] 117: [-16530*x^4 + 73563*x^3 - 174995*x^2 + 271134*x - 161425] 119: [378*x^4 + 819*x^3 + 1878*x^2 + 3938*x + 7386] 124: [63*x^4 + 130*x^3 + 268*x^2 + 551*x + 1132] 125: [16*x^4 + 33*x^3 + 68*x^2 + 140*x + 288] 126: [579103*x^4 + 50757882*x^3 - 171550192*x^2 + 356332674*x - 459859773] 128: [284*x^4 + 594*x^3 - 448*x^2 - 3088*x - 2030, 6844*x^4 - 4689*x^3 - 349 74*x^2 - 24615*x + 116962] 129: [121239*x^4 - 197007*x^3 - 764634*x^2 - 137825*x + 3066062] 130: [-148905438*x^4 + 497156819*x^3 - 1024997560*x^2 + 1307154759*x - 95299 62] 133: [-11850914*x^4 + 39486071*x^3 - 81306239*x^2 + 103476243*x - 50856] 136: [x^2 - x + 4] 137: [10436*x^4 + 28118*x^3 + 58568*x^2 + 93336*x + 154633] 138: [346952*x^4 - 739554*x^3 + 992969*x^2 - 172892*x - 3633389] 140: [391*x^4 + 16914*x^3 + 23679*x^2 - 33718*x - 127118] 141: [-6*x^4 + 5*x^3 + 10*x^2 - 52*x + 136] 142: [-3*x^4 - 5*x^3 + 32*x^2 - 80*x + 142, -42124*x^4 + 125551*x^3 - 239691 *x^2 + 266277*x + 129013, 13516*x^4 + 35437*x^3 - 1336*x^2 - 129548*x - 1131 15] 144: [525*x^4 + 1079*x^3 + 2223*x^2 + 4587*x + 9451, 155*x^4 - 521*x^3 - 132 0*x^2 + 529*x + 6269] 146: [12135*x^4 + 22239*x^3 + 42377*x^2 + 94551*x + 218424] 148: [297*x^4 - 224*x^3 - 1544*x^2 - 1015*x + 5254] 152: [439*x^4 + 73*x^3 - 1768*x^2 - 2559*x + 4239] 153: [-59*x^4 + 112*x^3 - 123*x^2 - 65*x + 738] 155: [772*x^4 - 2268*x^3 + 4283*x^2 - 4654*x - 2652] 157: [241448*x^4 + 417679*x^3 + 864708*x^2 + 2123175*x + 4787585] 160: [2*x - 4, 5*x^3 + 7*x^2 - 11*x - 41] 162: [277*x^4 + 572*x^3 + 1182*x^2 + 2432*x + 4987] 163: [-2245*x^4 + 3153*x^3 - 987*x^2 - 10078*x + 37758] 166: [3*x^4 - 4*x^3 + 17*x - 54] 169: [4*x^4 - 15*x^2 + 54*x - 108] 170: [6*x^4 - 2608*x^3 + 8663*x^2 - 17804*x + 22589] 171: [802*x^4 + 1651*x^3 + 3405*x^2 + 7019*x + 14438] 174: [41*x^4 + 8383*x^3 - 28101*x^2 + 58079*x - 74360] 175: [72*x^4 + 148*x^3 + 316*x^2 + 666*x + 1343] 177: [-82854*x^4 - 117450*x^3 + 202163*x^2 + 755931*x + 106537] 179: [-5089960*x^4 + 2068704*x^3 + 14685499*x^2 - 57692992*x + 129944660] 180: [x^2 - 3*x + 2] 182: [5804*x^4 - 5839*x^3 - 5152*x^2 + 41916*x - 117799] 185: [x^2 - 2*x] 186: [-11602*x^4 + 9070*x^3 + 18967*x^2 - 101636*x + 258187, -142431*x^4 - 4 80237*x^3 + 2203655*x^2 - 5305471*x + 8333030, 4*x^4 + 8*x^3 + 18*x^2 + 33*x + 75, -x^4 + 2*x^3 - 4*x^2 + 8*x + 1] 190: [x^2 - x - 2] 191: [99*x^4 + 176*x^3 + 284*x^2 + 603*x + 1597, 55*x^4 + 112*x^3 - 90*x^2 - 588*x - 364, 3*x^4 - 10*x^3 + 22*x^2 - 28*x + 6] 193: [-151377130*x^4 + 431708160*x^3 - 796483374*x^2 + 823328390*x + 6335835 09] 196: [6793545*x^4 - 10693841*x^3 + 6826578*x^2 + 22590870*x - 104198448] 197: [-22383064*x^4 + 43634035*x^3 - 50477245*x^2 - 16811671*x + 269988108] 199: [2*x^4 + 4*x^3 + 7*x^2 + 19*x + 29] 200: [9*x^4 - 15*x^3 + 12*x^2 + 24*x - 130] 201: [x^4 - 5*x^3 + 17*x^2 - 26*x + 34] 206: [-x + 3] 208: [-1723*x^4 - 323*x^3 + 6895*x^2 + 10147*x - 16309, -4616*x^4 + 77366*x^ 3 + 118173*x^2 - 177269*x - 725858] 212: [115365677*x^4 - 45854629*x^3 - 336294021*x^2 + 1314718510*x - 29542583 29] 213: [15*x^4 + 40*x^3 + 116*x^2 + 243*x + 363, 5266075*x^4 - 2073982*x^3 - 1 5414497*x^2 + 60143957*x - 135019482] 217: [-3*x^4 + 10*x^3 - 20*x^2 + 24*x + 2] 221: [2*x^4 + 4*x^3 + 8*x^2 + 17*x + 36] 223: [x^3 - x^2 + 4*x + 1] 224: [-12*x^4 - 18*x^3 + 28*x^2 + 112*x + 24, -209*x^4 + 305*x^3 + 1277*x^2 + 338*x - 4971] 225: [287*x^4 - 3825*x^3 + 11526*x^2 - 22183*x + 25040] 226: [2057*x^4 + 4233*x^3 + 8717*x^2 + 17959*x + 36984] 227: [-x^4 - x^3 + 3*x^2 + 8*x - 2] 233: [170*x^4 - 349*x^3 + 442*x^2 + 7*x - 1897] 234: [700*x^4 + 3609*x^3 + 1626*x^2 - 13228*x - 23721] 237: [x^4 + 2*x^3 + 4*x^2 + 8*x + 18] 238: [x^4 + 10*x^3 - 37*x^2 + 82*x - 114] 239: [-6315*x^4 + 83245*x^3 + 134364*x^2 - 178484*x - 789649] 243: [3] 245: [284*x^4 + 92*x^3 + 909*x^2 + 4876*x + 10812] 247: [-1023*x^4 + 3286*x^3 + 8521*x^2 - 3081*x - 40030] 248: [-5798*x^4 + 3231*x^3 + 13815*x^2 - 59720*x + 140388] 250: [95029*x^4 - 123210*x^3 + 7619*x^2 + 496926*x - 1687762] 252: [-3*x^4 + 23*x^3 + 42*x^2 - 44*x - 234] 256: [209*x^4 - 171*x^3 - 315*x^2 + 1777*x - 4579, -120*x^4 - 4*x^3 + 522*x^ 2 - 1722*x + 3524, -x^4 + 2*x^3 - 2*x^2 + 9] 258: [-x^4 + 3*x^3 + 8*x^2 - 2*x - 38] 259: [-9*x^4 + 14*x^3 + 56*x^2 + 12*x - 222] 260: [-6*x^4 - 16*x^3 + 23*x^2 + 134*x + 149] 265: [279*x^4 + 1656*x^3 + 925*x^2 - 5842*x - 11353] 266: [-15*x^4 + 5*x^3 + 70*x^2 + 68*x - 210] 267: [-8229*x^4 + 28696*x^3 - 60714*x^2 + 80616*x - 11188] 269: [x^3 + 2*x^2 - 3*x - 11] 272: [-329717*x^4 - 475679*x^3 + 792461*x^2 + 3024939*x + 489939, -19260*x^4 + 3158851*x^3 - 10441779*x^2 + 21394937*x - 27010829] 274: [x^4 + 2*x^3 + 4*x^2 + 9*x + 18] 276: [581*x^4 + 370*x^3 - 1992*x^2 - 4103*x + 3224] 279: [-1826756*x^4 + 4986049*x^3 - 8866643*x^2 + 8401714*x + 9597647] 280: [x + 3] 281: [-11*x^4 + 26*x^3 - 40*x^2 + 23*x + 93, 77986*x^4 + 198610*x^3 + 514566 *x^2 + 1032612*x + 1644077, -46143*x^4 + 67240*x^3 - 28396*x^2 - 190443*x + 754819] 282: [196079*x^4 + 9567*x^3 - 816242*x^2 - 1073455*x + 2106085] 284: [-93394*x^4 + 60075*x^3 + 478379*x^2 + 366460*x - 1536088, -157*x^4 + 5 8*x^3 + 791*x^2 + 867*x - 2031, x^2 + 3*x + 4] 288: [-190*x^4 - 72*x^3 + 1046*x^2 - 3178*x + 6156, 58*x^4 + 263*x^3 - 1122* x^2 + 2623*x - 3982] 289: [42*x^4 + 68*x^3 + 84*x^2 + 180*x + 617] 291: [-68488791*x^4 + 28662621*x^3 + 194848612*x^2 - 770626148*x + 174127494 7] 292: [x^4 + 2*x^3 + 4*x^2 + 9*x + 16] 293: [-173123*x^4 + 1161964*x^3 - 3137080*x^2 + 5525136*x - 5107878] 296: [-2*x^4 + 261*x^3 - 861*x^2 + 1762*x - 2220] 304: [19*x^4 - 243*x^3 + 731*x^2 - 1401*x + 1577, -62*x^4 + 259*x^3 - 600*x^ 2 + 901*x - 458] 306: [-72981*x^4 + 634070*x^3 + 1116239*x^2 - 1267500*x - 6344734] 310: [20259*x^4 + 49809*x^3 + 229335*x^2 + 599186*x + 857837] 313: [-11471*x^4 + 91948*x^3 + 165652*x^2 - 178948*x - 929842] 314: [20*x^4 + 42*x^3 + 86*x^2 + 173*x + 353] 315: [15*x^3 - 50*x^2 + 103*x - 131] 317: [26*x^4 - 70*x^3 + 123*x^2 - 113*x - 145] 320: [-715016*x^4 - 1436884*x^3 + 7817922*x^2 - 19953504*x + 33331798, -1081 8*x^4 + 18021*x^3 - 14176*x^2 - 29168*x + 157265] 321: [4360*x^4 + 9021*x^3 + 18634*x^2 + 38256*x + 78370] 323: [-402698*x^4 + 158391*x^3 + 1908700*x^2 + 1757439*x - 5854795] 324: [59*x^4 + 559*x^3 - 2112*x^2 + 4667*x - 6593] 325: [x^3 + 2*x^2 + 14] 326: [213271*x^4 + 448404*x^3 + 949328*x^2 + 1948400*x + 3893091] 327: [1312*x^4 + 2690*x^3 + 5512*x^2 + 11363*x + 23526] 332: [-34628262*x^4 + 27740099*x^3 + 54381419*x^2 - 298761718*x + 764765542] 333: [-36*x^4 + 523*x^3 - 1589*x^2 + 3078*x - 3515] 337: [31398*x^4 - 57827*x^3 + 59544*x^2 + 46773*x - 408237] 338: [-139953*x^4 - 382867*x^3 + 110583*x^2 + 1773000*x + 1806375] 340: [-461*x^4 - 5016*x^3 - 4154*x^2 + 16543*x + 39824] 342: [-131*x^4 + 487*x^3 - 1066*x^2 + 1489*x - 437] 343: [19831*x^4 - 47808*x^3 - 135700*x^2 + 48936*x + 676534] 345: [x^2 - 4] 347: [393095*x^4 - 806794*x^3 + 1021365*x^2 + 17551*x - 4388208] 348: [2750*x^4 + 1189*x^3 - 10123*x^2 - 17877*x + 20257] 349: [-94370*x^4 - 184667*x^3 + 165066*x^2 + 992882*x + 563692] 350: [-435*x^4 + 622*x^3 - 228*x^2 - 1877*x + 7220] 354: [x^4 + x^3 - 3*x^2 - 8*x + 3] 355: [119*x^4 + 176*x^3 + 403*x^2 + 1174*x + 2683, x^4 + 2*x^3 + 4*x^2 + 9*x + 19, -20559*x^4 + 26813*x^3 - 2172*x^2 - 106429*x + 363766] 358: [67*x^4 + 301*x^3 + 99*x^2 - 1150*x - 1883] 359: [3*x^3 - 10*x^2 + 21*x - 27] 360: [-360934*x^4 + 4627403*x^3 - 13885713*x^2 + 26642651*x - 29893695] 361: [-112*x^4 + 244*x^3 - 335*x^2 + 88*x + 1140] 364: [-155*x^4 - 3056*x^3 - 3149*x^2 + 9118*x + 25302] 365: [119204*x^4 - 250756*x^3 + 330045*x^2 - 36518*x - 1277460] 370: [-718442*x^4 + 3908961*x^3 - 9976752*x^2 + 16665899*x - 13227796] 371: [-34641*x^4 + 160448*x^3 + 351019*x^2 - 233495*x - 1785138] 372: [-151*x^4 + 1096*x^3 + 2144*x^2 - 1693*x - 10780, 88*x^4 + 81*x^3 - 267 *x^2 - 677*x + 283, -779081*x^4 + 5131030*x^3 - 13790905*x^2 + 24191847*x - 22130971, 52905*x^4 + 2341*x^3 - 232072*x^2 + 763203*x - 1558749] 373: [-7*x^4 - 5*x^3 + 47*x^2 - 134*x + 250] 380: [-1075950*x^4 + 3190519*x^3 - 6067791*x^2 + 6689147*x + 3438103] 381: [57727*x^4 + 148801*x^3 + 285231*x^2 + 433426*x + 786240] 382: [51*x^4 - 127*x^3 + 207*x^2 - 151*x - 374, 294*x^4 - 873*x^3 + 1662*x^2 - 1836*x - 929, -289473*x^4 + 50508*x^3 + 1294621*x^2 + 1439915*x - 3642173 ] 386: [730*x^4 + 1503*x^3 + 3089*x^2 + 6353*x + 13095] 392: [6*x^4 - 15*x^3 - 43*x^2 + 12*x + 204] 394: [679*x^4 + 1411*x^3 + 2866*x^2 + 5796*x + 11966] 398: [-441717*x^4 - 4114047*x^3 + 15578087*x^2 - 34456844*x + 48751711] 400: [-14121*x^4 - 42463*x^3 + 5833*x^2 + 187441*x + 213811, -485552*x^4 + 4 0941*x^3 + 2110863*x^2 + 2513370*x - 5748258] 402: [-233347*x^4 - 322792*x^3 + 588962*x^2 + 2139460*x + 270287] 403: [78*x^4 + 316*x^3 - 1381*x^2 + 3266*x - 5016] 405: [1011048403*x^4 - 1415314931*x^3 + 428988586*x^2 + 4570622078*x - 17045 167535] 412: [533623*x^4 + 713164*x^3 - 4637959*x^2 + 12427717*x - 21740721] 415: [7002*x^4 - 19830*x^3 - 54916*x^2 + 14183*x + 250846] 416: [12*x^3 - 40*x^2 + 82*x - 104, -x^3 - x^2 + 3*x + 7] 417: [-35136*x^4 - 13626*x^3 + 131611*x^2 + 225241*x - 271295] 419: [560*x^4 + 1235*x^3 + 2463*x^2 + 4622*x + 9283] 424: [453*x^4 + 931*x^3 + 1907*x^2 + 3921*x + 8108] 425: [6*x^4 + 12*x^3 + 21*x^2 + 40*x + 94] 426: [-307*x^4 + 457*x^3 - 221*x^2 - 1201*x + 4938, 75*x^4 - 4*x^3 - 323*x^2 - 394*x + 868] 434: [229020*x^4 - 2937*x^3 - 961070*x^2 + 3214168*x - 6633571] 435: [2*x^3 + 5*x^2 + 3*x - 7] 439: [340*x^4 - 658*x^3 + 751*x^2 + 288*x - 4142] 441: [-x^3 - x^2 + 2*x + 9] 442: [72646*x^4 - 242032*x^3 + 498349*x^2 - 634190*x + 161] 443: [-52874*x^4 - 359697*x^3 - 233432*x^2 + 1228056*x + 2552814] 446: [3334966*x^4 - 10447057*x^3 + 20665939*x^2 - 24559864*x - 5787442] 447: [3023*x^4 - 8573*x^3 - 23724*x^2 + 6154*x + 108401] 448: [4174*x^4 + 4308*x^3 - 32046*x^2 + 88496*x - 158968, 48*x^4 - 86*x^3 + 83*x^2 + 88*x - 645] 450: [-14171*x^4 + 24148*x^3 + 90804*x^2 + 13185*x - 368144] 452: [-17*x^4 + 280*x^3 - 858*x^2 + 1677*x - 1938] 454: [42409*x^4 + 90034*x^3 - 479719*x^2 + 1216471*x - 2018953] 455: [2*x^4 + 4*x^3 + 6*x^2 + 10*x + 27] 457: [-87*x^4 - 185*x^3 + 134*x^2 + 956*x + 651] 461: [-x^4 + 2*x^3 - 3*x^2 + 4*x + 5] 463: [-11*x^4 + 5*x^3 + 30*x^2 - 121*x + 276] 465: [2*x^4 + 4*x^3 + 9*x^2 + 20*x + 40, x^2 - x + 3, 4609*x^4 + 1282*x^3 - 17907*x^2 - 28221*x + 40000, -4156*x^4 - 116355*x^3 - 130442*x^2 + 327263*x + 969403] 466: [1159032*x^4 + 2381161*x^3 + 4715244*x^2 + 9491919*x + 20062122] 468: [6*x^4 - 26*x^3 + 61*x^2 - 93*x + 52] 474: [38962*x^4 + 243483*x^3 - 976308*x^2 + 2220316*x - 3258047] 475: [-28292*x^4 - 18315*x^3 + 96637*x^2 + 200626*x - 154333] 476: [149520*x^4 - 433375*x^3 - 1184038*x^2 + 333085*x + 5448548] 477: [3*x^4 + 6*x^3 + 12*x^2 + 25*x + 53] 478: [-x^3 - x^2 + 3*x + 9] 481: [6*x^4 - 20*x^3 + 41*x^2 - 52*x] 483: [-21*x^4 - 4*x^3 + 84*x^2 + 124*x - 198] 486: [528345*x^4 - 15834*x^3 - 2186994*x^2 + 7352895*x - 15224466] 487: [5668*x^4 - 14258*x^3 + 23472*x^2 - 17752*x - 40361] 490: [2*x^4 - 3*x^3 + 2*x^2 + 7*x - 30] 491: [-1888*x^4 - 8569*x^3 - 2900*x^2 + 32636*x + 53824, -6486*x^4 + 17022*x ^3 - 29212*x^2 + 25158*x + 40023, 1027*x^4 + 866*x^3 - 3228*x^2 - 7730*x + 3 948] 494: [6*x^4 - 14*x^3 + 21*x^2 - 11*x - 52] 496: [33*x^4 - 31*x^3 - 177*x^2 - 89*x + 647, -306*x^4 - 1960*x^3 - 1005*x^2 + 7425*x + 14522] 497: [3457*x^4 - 2824*x^3 - 15097*x^2 - 751*x + 76402, 10*x^4 + 5*x^3 - 9*x^ 2 + 23*x + 182, x^3 - 2*x^2 + 5*x - 3] 499: [2374*x^4 - 1671*x^3 - 4497*x^2 + 22065*x - 54444] 500: [52*x^4 - 247*x^3 - 486*x^2 + 529*x + 2940] ? bnfisintnorm(bnfinit(x^3+5),5) [-x] ? print("Total time spent: ",gettime); Total time spent: 620 pari-2.5.5/src/test/32/ff0000644000175000017500000001654012147140047013422 0ustar billbill *** Warning: new stack size = 50000000 (47.684 Mbytes). ? 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], 0, a/x, 1, a^18 + a^15 + a ^14 + a^11 + a^9 + a^8 + a^6 + a^5 + 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, 0, 0, 0, 0, 0, 0], a/ x, (x + a)/(x + 6*a), 5*a^6 + 6*a^5 + 6*a^4 + 3*a^3 + 6*a^2 + a + 2, 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, 0, 0, 0, 0 , 0, 0], a/x, (x + a)/(x + 4294967290*a), 2288583118*a^2 + 3771341620*a + 20 59371838, 36893488070109691946, a, [x + (1365670490*a^2 + 3373566631*a + 408 3593885), 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, 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, 0, 0, 0, 0, 0, 0], a/x, (x + a)/(x + 4294967310*a), 304446768*a^2 + 184758295*a + 3792851449, 614891473561784601 1, a, [x + (268392743*a^2 + 2459390605*a + 1304316255), 1; x + (4026574568*a ^2 + 1835576706*a + 2990651057), 1], [268392743*a^2 + 2459390605*a + 1304316 254, 4026574568*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)]] 1 ? test2(3) [2, [2, Mat([2, 1])]] 1 ? test2(46744073709551653) [2, [46744073709551652, [2, 2; 3, 1; 7, 1; 37, 1; 1036513, 1; 14510113, 1]]] *** at top-level: test2(46744073709551 *** ^-------------------- *** in function test2: ...d(1,p)),&o);print([g,o]);fflog(g^17,g,o) *** ^--------------- *** fflog: gen_Shanks_log: supplied order (= 2) is incorrect. ? test2(precprime(1<<32)) [2, [4294967290, [2, 1; 5, 1; 19, 1; 22605091, 1]]] 17 ? 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(ffinit(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(ffinit(7,4));fflog(t^6,t^2) *** at top-level: t=ffgen(ffinit(7,4));fflog(t^6,t^2) *** ^-------------- *** fflog: gen_Shanks_log: supplied order (= 5) is incorrect. ? t=ffgen(ffinit(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) []~ ? print("Total time spent: ",gettime); Total time spent: 508 pari-2.5.5/src/test/32/subcyclo0000644000175000017500000000014611636712103014645 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.5.5/src/test/32/sumiter0000644000175000017500000000232012147140047014506 0ustar billbill realprecision = 19 significant digits echo = 1 (on) ? gettime;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.0000098157493066238697591433298145196 ? prodinf(n=0,(1+2^-n)/(1+2^(-n+1))) 0.33333333333333333333333333333333333324 ? prodinf(n=0,-2^-n/(1+2^(-n+1)),1) 0.33333333333333333333333333333333333324 ? 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) 1.0000000000000000000000000000000000000 ? 6/Pi^2*sumpos(n=1,n^-2) 1.0000000000000000000000000000000000000 ? getheap [20, 196] ? print("Total time spent: ",gettime); Total time spent: 16 pari-2.5.5/src/test/32/padic0000644000175000017500000000156212147140047014105 0ustar billbill[0]~ *** at top-level: padicappr(x^2+1+O(3) *** ^-------------------- *** padicappr: different primes in Zp_to_Z: 5 != 3. *** at top-level: padicappr(x^2+1+O(3) *** ^-------------------- *** padicappr: different primes in Zp_to_Z: 5 != 3. [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] Total time spent: 0 pari-2.5.5/src/test/32/compat0000644000175000017500000026520512212100640014302 0ustar billbill echo = 1 (on) ? default(compatible,3) *** default: Warning: user functions re-initialized. ? gettime;+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=57 realprecision = 57 significant digits ? pi 3.14159265358979323846264338327950288419716939937510582098 ? \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, [0.83756543528332303 544481089907503024040, 0.26959443640544455826293795134926000405, -1.10715987 16887675937077488504242902445]~, 2.9934586462319596298320099794525081778, -2 .4513893819867900608542248318665252254*I, 0.94263855591362295176518779416067 539931, 1.3270305788796764757190502098362372906*I, 7.33813274078957673907072 10033323055880] ? 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.072312766896812300380582649294307897075 + 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]]], [-2.428 5174907194186068992069565359418365, 1.9647119211288133163138753392090569931 + 0.80971492418897895128294082219556466857*I, -0.750453175769104012864271860 94108607489 + 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.54930614433405484569762261846126285233 ? 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, [4.1231056256176605 498214098559740770251, 0.E-48, -4.1231056256176605498214098559740770251]~, 1 .2913084409290072207105564235857096010, -1.291308440929007220710556423585709 6010*I, 2.4328754881596176532948539893637583869, 2.4328754881596176532948539 893637583869*I, 1.6674774896145033307120230298772362382] ? 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.0045457500000000000000000000000000000001 ? 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, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.71246530518434397468087951060 61300698 + 9.4247779607693797153879301498385086522*I; 2.71246530518434397468 08795106061300698 + 6.2831853071795864769252867665590057686*I], [-0.92212354 848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.70148550268542821846861610071436 900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.50057980363245 587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.623 6090511720428168202836906902792025, -0.5788359042095875039617797232424909750 4, -0.34328764427702709438988786673341921877 + 3.141592653589793238462643383 2795028842*I, 0.066178301882745732185368492323164193427 + 3.1415926535897932 384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.922123 54848661459835166758997591019383, 1.4227033521190704721778709033666269682, - 0.70148550268542821846861610071436900869 + 3.1415926535897932384626433832795 028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.6236090511720 428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.5788 3590420958750396177972324249097504, 0.34328764427702709438988786673341921877 , -0.066178301882745732185368492323164193427, 0.9883018503693603305370360822 9907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57 ; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, - 2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0] ]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.066372975210777963595931024670 5326059; 1, 8.0663729752107779635959310246705326059], [1, -7.066372975210777 9635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.06637297521077796359 59310246705326059], [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]], [[-0.92212354848661459835166758997591019383 + 3.1 415926535897932384626433832795028842*I, 0.9221235484866145983516675899759101 9383]]], 0] ? buchcertify(bnf) 1 ? buchfu(bnf) [x + 7] ? setrand(1);buchinitforcefu(x^2-x-100000) [mat(5), mat([3, 2, 1, 2, 0, 3, 2, 3, 3, 2, 0, 0, 4, 1, 3, 2, 2, 3]), [-129. 82045011403975460991182396195022419 - 3.234427763 E-65*I; 129.82045011403975 460991182396195022419 + 1.513356110 E-65*I], [-41.81126458912994339333950225 8694361489 + 6.2831853071795864769252867665590057684*I, 9.239900414790228981 6376260438840931575 + 6.2831853071795864769252867665590057684*I, -11.8746098 81075406725097315997431161032 + 3.1415926535897932384626433832795028842*I, 0 , 598.05108556627860067458199150717266631 + 6.283185307179586476925286766559 0057684*I, -194.73067517105963191486773594292533629 + 3.14159265358979323846 26433832795028842*I, -289.57755493613404588806583418516364884 + 3.1415926535 897932384626433832795028842*I, 102.98937362955842429020308089254908188 + 9.4 9556775 E-66*I, -404.44153844676787690336623107514389175 + 3.141592653589793 2384626433832795028842*I, 484.20828704532476310708802954016117339 + 3.141592 6535897932384626433832795028842*I, 123.08269893574406654913158801089558608 + 6.2831853071795864769252867665590057684*I, -731.254381612670293662138025288 99365727, 601.43393149863053905222620132704343308 + 6.2831853071795864769252 867665590057684*I, 1093.4420050106303665241166125712749392 + 3.1415926535897 932384626433832795028842*I, -745.79191925764104608772064294411862807 + 3.141 5926535897932384626433832795028842*I, -671.206766092812650930409714233567335 50, 239.93415116156344370733474008902230144 + 3.1415926535897932384626433832 795028842*I, 652.97854421667665555630760228878662857 + 3.1415926535897932384 626433832795028842*I, -1733.3534097181246358289416962430827836; 41.811264589 129943393339502258694361489 + 8.30862178 E-66*I, -9.239900414790228981637626 0438840931575 + 3.1415926535897932384626433832795028842*I, 11.87460988107540 6725097315997431161032 + 6.2831853071795864769252867665590057684*I, 0, -598. 05108556627860067458199150717266631 + 3.141592653589793238462643383279502884 2*I, 194.73067517105963191486773594292533629 + 3.798227099 E-65*I, 289.57755 493613404588806583418516364884 + 4.747783872 E-65*I, -102.989373629558424290 20308089254908188 + 3.1415926535897932384626433832795028842*I, 404.441538446 76787690336623107514389175 + 5.697340648 E-65*I, -484.2082870453247631070880 2954016117339 + 6.2831853071795864769252867665590057684*I, -123.082698935744 06654913158801089558608 + 3.1415926535897932384626433832795028842*I, 731.254 38161267029366213802528899365727 + 1.139468130 E-64*I, -601.4339314986305390 5222620132704343308 + 6.2831853071795864769252867665590057684*I, -1093.44200 50106303665241166125712749392 + 3.1415926535897932384626433832795028842*I, 7 45.79191925764104608772064294411862807 + 3.141592653589793238462643383279502 8842*I, 671.20676609281265093040971423356733550 + 3.141592653589793238462643 3832795028842*I, -239.93415116156344370733474008902230144 + 6.28318530717958 64769252867665590057684*I, -652.97854421667665555630760228878662857 + 3.1415 926535897932384626433832795028842*I, 1733.3534097181246358289416962430827836 + 2.278936259 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]], [31, [23, 1]~, 1, 1, [7, 100000; 1, 8]], [31, [38, 1]~, 1, 1, [-8, 100000; 1 , -7]], [17, [14, 1]~, 1, 1, [2, 100000; 1, 3]], [17, [19, 1]~, 1, 1, [-3, 1 00000; 1, -2]], [23, [-7, 1]~, 1, 1, [6, 100000; 1, 7]], [23, [6, 1]~, 1, 1, [-7, 100000; 1, -6]], [29, [-14, 1]~, 1, 1, [13, 100000; 1, 14]], [29, [13, 1]~, 1, 1, [-14, 100000; 1, -13]], [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 - 10000 0, [2, 0], 400001, 1, [[1, -315.72816130129840161392089489603747004; 1, 316. 72816130129840161392089489603747004], [1, -315.72816130129840161392089489603 747004; 1, 316.72816130129840161392089489603747004], [1, -316; 1, 317], [2, 1; 1, 200001], [400001, 200000; 0, 1], [200001, -1; -1, 2], [400001, [200000 , 100000; 1, 200001]]], [-315.72816130129840161392089489603747004, 316.72816 130129840161392089489603747004], [1, x], [1, 0; 0, 1], [1, 0, 0, 100000; 0, 1, 1, 1]], [[5, [5], [[2, 1; 0, 1]]], 129.8204501140397546099118239619502241 9, 1, [2, -1], [379554884019013781006303254896369154068336082609238336*x + 1 19836165644250789990462835950022871665178127611316131167]], [mat(1), [[0, 0] ], [[-41.811264589129943393339502258694361489 + 6.28318530717958647692528676 65590057684*I, 41.811264589129943393339502258694361489 + 8.30862178 E-66*I]] ], 0] ? setrand(1);bnf=buchinitfu(x^2-x-57,0.2,0.2) [mat(3), mat([1, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.71246530518434397468087951060 61300698 + 9.4247779607693797153879301498385086522*I; 2.71246530518434397468 08795106061300698 + 6.2831853071795864769252867665590057686*I], [-0.92212354 848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.70148550268542821846861610071436 900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.50057980363245 587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.623 6090511720428168202836906902792025, -0.5788359042095875039617797232424909750 4, -0.34328764427702709438988786673341921877 + 3.141592653589793238462643383 2795028842*I, 0.066178301882745732185368492323164193427 + 3.1415926535897932 384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.922123 54848661459835166758997591019383, 1.4227033521190704721778709033666269682, - 0.70148550268542821846861610071436900869 + 3.1415926535897932384626433832795 028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.6236090511720 428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.5788 3590420958750396177972324249097504, 0.34328764427702709438988786673341921877 , -0.066178301882745732185368492323164193427, 0.9883018503693603305370360822 9907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57 ; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, - 2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0] ]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.066372975210777963595931024670 5326059; 1, 8.0663729752107779635959310246705326059], [1, -7.066372975210777 9635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.06637297521077796359 59310246705326059], [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]], [[-0.92212354848661459835166758997591019383 + 3.1 415926535897932384626433832795028842*I, 0.9221235484866145983516675899759101 9383]]], 0] ? setrand(1);buchreal(10^9-3,0,0.5,0.5) [4, [4], [qfr(229, 31609, -951, 0.E-48)], 2800.62525190701607648637062173707 45514] ? 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.229975145405511722395637833443108784] [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], [[17, 2; 0, 1]]]] [129.82045011403975460991182396194763531] [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, 3, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]]]] [3.7941269688216589341408274220859400302] [1] [[6, 10/1029*x^3 - 13/343*x^2 + 165/343*x + 1478/343]] [[4/1029*x^3 + 53/1029*x^2 + 66/343*x + 111/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, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.7124653051843439746808795106 061300698 + 9.4247779607693797153879301498385086522*I; 2.7124653051843439746 808795106061300698 + 6.2831853071795864769252867665590057686*I], [-0.9221235 4848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.7014855026854282184686161007143 6900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.5005798036324 5587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.62 36090511720428168202836906902792025, -0.578835904209587503961779723242490975 04, -0.34328764427702709438988786673341921877 + 3.14159265358979323846264338 32795028842*I, 0.066178301882745732185368492323164193427 + 3.141592653589793 2384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.92212 354848661459835166758997591019383, 1.4227033521190704721778709033666269682, -0.70148550268542821846861610071436900869 + 3.141592653589793238462643383279 5028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.623609051172 0428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.578 83590420958750396177972324249097504, 0.3432876442770270943898878667334192187 7, -0.066178301882745732185368492323164193427, 0.988301850369360330537036082 29907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 5 7; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, -2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0 ]]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.06637297521077796359593102467 05326059; 1, 8.0663729752107779635959310246705326059], [1, -7.06637297521077 79635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7 ; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.0663729752107779635 959310246705326059], [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]], [[-0.92212354848661459835166758997591019383 + 3. 1415926535897932384626433832795028842*I, 0.922123548486614598351667589975910 19383]]], [0, [mat([[5, 1]~, 1])]]], [[[5, 3; 0, 1], [1, 0]], [8, [4, 2], [2 , [-4, 0]~]], mat([[5, [-2, 1]~, 1, 1, [1, 1]~], 1]), [[[[4], [[2, 0]~], [[2 , 0]~], [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, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.7124653051843439746808795106 061300698 + 9.4247779607693797153879301498385086522*I; 2.7124653051843439746 808795106061300698 + 6.2831853071795864769252867665590057686*I], [-0.9221235 4848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.7014855026854282184686161007143 6900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.5005798036324 5587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.62 36090511720428168202836906902792025, -0.578835904209587503961779723242490975 04, -0.34328764427702709438988786673341921877 + 3.14159265358979323846264338 32795028842*I, 0.066178301882745732185368492323164193427 + 3.141592653589793 2384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.92212 354848661459835166758997591019383, 1.4227033521190704721778709033666269682, -0.70148550268542821846861610071436900869 + 3.141592653589793238462643383279 5028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.623609051172 0428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.578 83590420958750396177972324249097504, 0.3432876442770270943898878667334192187 7, -0.066178301882745732185368492323164193427, 0.988301850369360330537036082 29907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 5 7; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, -2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0 ]]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.06637297521077796359593102467 05326059; 1, 8.0663729752107779635959310246705326059], [1, -7.06637297521077 79635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7 ; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.0663729752107779635 959310246705326059], [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]], [[-0.92212354848661459835166758997591019383 + 3. 1415926535897932384626433832795028842*I, 0.922123548486614598351667589975910 19383]]], [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, 1]~], 2]), [[[[4 ], [[2, 0]~], [[2, 0]~], [Vecsmall([0, 0])], 1], [[5], [[6, 0]~], [[6, 0]~], [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]], [1], mat([1, -3, -6, -6]), [12, [12], [[3, 2; 0, 1]]], [[0, 2, 0; -1, 10, 0], [- 2, 0; 0, -10], 2]] ? bytesize(%) 6648 ? 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, [-0.1624345647 1667696455518910092496975960, -0.73040556359455544173706204865073999595, -2. 1071598716887675937077488504242902445]~, -2.99345864623195962983200997945250 81778, 2.4513893819867900608542248318665252254*I, -0.94263855591362295176518 779416067539931, -1.3270305788796764757190502098362372906*I, 7.3381327407895 767390707210033323055880] ? 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 698368 + 0.18258225455744299269398828369501930574*I, 0.460202188254280606994 79112458168698368 - 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]) [mod(6, 7), mod(5, 7)]~ ? 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.2833494518006402717978106547571267252 1 0.283349451800640271797810654757 12672521] [-0.14167472590032013589890532737856336261 -2 0.6416747259003201358989053273 7856336260] [1 1 1] ? eint1(2) 0.048900510708061119567239835228049522312 ? 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 - 2*x^4 - 62*x^3 + 85*x^2 + 818*x + 1, x^5 - 2*x^4 - 53*x^3 - 46 *x^2 + 508*x + 913, x^5 - 2*x^4 - 13*x^3 + 37*x^2 - 21*x - 1, x^5 - x^4 - 52 *x^3 - 197*x^2 - 273*x - 127] ? factoredpolred2(p,fa) [x - 1, x^5 - 2*x^4 - 62*x^3 + 85*x^2 + 818*x + 1, x^5 - 2*x^4 - 53*x^3 - 46 *x^2 + 508*x + 913, x^5 - 2*x^4 - 13*x^3 + 37*x^2 - 21*x - 1, x^5 - x^4 - 52 *x^3 - 197*x^2 - 273*x - 127] ? 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 ? getheap() [208, 45748] ? 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, 1472584495, -664748218, -927756173, -1863 993863, -1149321316, 1135347562, 1205814267, -1293541270, 806702053, -631730 419, 2120242162, 1259144634, -259813841, -1748638985, -481185123, 459357013, 139809444, -1094803819, -956855999, -365358884, -39929854, 1096255899, 2017 713822, 1464920131, -953056017, -564919260, -823296656, -777957747, -1166640 119, -409307993, -160471003, 1950881272, 2140986234, 1617664168, -179627494, 1618528081, 949905077, 1996141541, -1056917386, -1728441144, -389361315, 18 69686534, -2072896478, -751871013, -1178639831, 1962418281, -690140718, -191 8297446, -68103184, -1955591658, 1354080479, -14042013, -129902947, 20183230 7, -620608254, -1243546160, -48623379, -479563203, -732434165, -294635956, 1 935166130, 42381710, 876975196, 66, -1981709264]) ? getstack() 104 ? globalred(acurve) [37, [1, -1, 2, 2], 1] ? getstack() 104 ? 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 837196 - 1.5701452385894131769052374806001981109*I; 1, 1.6829412935943127761 629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.750453175 76910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, - 0.78742068874775359433940488309213323160 + 2.1336633893126618034168454610457 936016*I, 1.2658732110596551455718089553258673705 - 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]]], [-1.0891151457205048250249527946671612684, -0.13838372073406036365047 976417441696637 + 0.49181637657768643499753285514741525107*I, 1.682941293594 3127761629561615079976006 + 2.0500351226010726172974286983598602164*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 2837196 - 1.5701452385894131769052374806001981109*I; 1, 1.682941293594312776 1629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.75045317 576910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, -0.78742068874775359433940488309213323160 + 2.133663389312661803416845461045 7936016*I, 1.2658732110596551455718089553258673705 - 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]]], [-1.0891151457205048250249527946671612684, -0.1383837207340603636504 7976417441696637 + 0.49181637657768643499753285514741525107*I, 1.68294129359 43127761629561615079976006 + 2.0500351226010726172974286983598602164*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, -1, -1, -1, 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, -1, -1, -1, 0]~] 1] [[5, [-1, 0, 0, 0, 2]~, 4, 1, [2, 2, 1, 2, 1]~] 3] [[5, [2, 0, 0, 0, -2]~, 1, 1, [2, 0, 3, 0, 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, [1.0000000000000000000000000 000000000000, 0.E-48, -1.0000000000000000000000000000000000000]~, 2.62205755 42921198104648395898911194137, -2.6220575542921198104648395898911194137*I, 1 .1981402347355922074399224922803238782, 1.1981402347355922074399224922803238 782*I, 6.8751858180203728274900957798105571979] ? 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.124450933778112631 ? \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 840494514780771076350, 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, [1.732050807568877294, 0. E-28, -1.732050807568877294]~, 1.992332899583490707, -1.992332899583490707*I , 1.576841226808312136, 1.576841226808312136*I, 3.969390382762759667] ? 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, [0.8375654352833230 354, 0.2695944364054445583, -1.107159871688767594]~, 2.993458646231959630, - 2.451389381986790061*I, 0.9426385559136229515, 1.327030578879676476*I, 7.338 132740789576739] ? l=lseriesell(ccurve,2,-37,1) 0.3815754082607112104 ? lseriesell(ccurve,2,-37,1.2)-l -2.276824562 E-18 ? 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, 1, 1]), [9, 15, 16, 33, 39, 17, 10, 57, 69], [2, -1], [[0, 1, 0]~, [ 5, 3, 1]~], [[[4, -1, 0]~, [1, -1, 0]~, [-2, -1, 0]~, [1, 1, 0]~, [10, 5, 1] ~, [3, 1, 0]~, [3, 0, 0]~, [7, 2, 0]~, [-2, -1, 1]~], 0]] ? makebigbnf(sbnf) [mat(2), mat([1, 1, 0, 1, 0, 1, 1, 1]), [1.173637103435061715 + 3.1415926535 89793239*I, -4.562279014988837911 + 3.141592653589793239*I; -2.6335434327389 76050 + 3.141592653589793239*I, 1.420330600779487358 + 3.141592653589793239* I; 1.459906329303914335, 3.141948414209350544], [1.246346989334819161, 0.540 4006376129469728, -0.6926391142471042845, 0.004375616572659815433 + 3.141592 653589793239*I, -0.8305625946607188642 + 3.141592653589793239*I, -1.99005644 5584799713 + 3.141592653589793239*I, 0, -1.977791147836553954, 0.36772620140 27817707; 0.6716827432867392935, -0.8333219883742404172, -0.2461086674077943 078 + 3.141592653589793239*I, -0.8738318043071131265, -1.552661549868775854, 0.5379005671092853266, 0, 0.5774919091398324093, 0.9729063188316092381 + 3. 141592653589793239*I; -1.918029732621558454 + 3.141592653589793239*I, 0.2929 213507612934446 + 3.141592653589793239*I, 0.9387477816548985924 + 3.14159265 3589793239*I, 0.8694561877344533112, 2.383224144529494719, 1.452155878475514 387, 0, 1.400299238696721545, -1.340632520234391008 + 3.141592653589793239*I ], [[3, [-1, 1, 0]~, 1, 1, [1, 1, 1]~], [5, [-1, 1, 0]~, 1, 1, [0, 1, 1]~], [5, [2, 1, 0]~, 1, 1, [1, -2, 1]~], [11, [1, 1, 0]~, 1, 1, [-3, -1, 1]~], [1 3, [19, 1, 0]~, 1, 1, [-2, -6, 1]~], [5, [3, 1, 0]~, 1, 1, [2, 2, 1]~], [3, [10, 1, 1]~, 1, 2, [-1, 1, 0]~], [19, [-6, 1, 0]~, 1, 1, [6, 6, 1]~], [23, [ -10, 1, 0]~, 1, 1, [-7, 10, 1]~]]~, 0, [x^3 - x^2 - 14*x - 1, [3, 0], 10889, 1, [[1, -3.233732695981516673, 4.690759845041404812; 1, -0.0718235090274363 6345, -8.923017874523549404; 1, 4.305556205008953037, 5.232258029482144592], [1, -3.233732695981516673, 4.690759845041404812; 1, -0.07182350902743636345 , -8.923017874523549404; 1, 4.305556205008953037, 5.232258029482144592], [1, -3, 5; 1, 0, -9; 1, 4, 5], [3, 1, 1; 1, 29, 8; 1, 8, 129], [10889, 5698, 89 94; 0, 1, 0; 0, 0, 1], [3677, -121, -21; -121, 386, -23; -21, -23, 86], [108 89, [1899, 46720, 5235; 5191, 7095, 25956; 1, 5191, 1895]]], [-3.23373269598 1516673, -0.07182350902743636345, 4.305556205008953037], [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.34800724602768001, 1, [2, -1], [x, x^2 + 2*x - 4]], [mat(1), [[0, 0, 0]], [[1.246346989334819161, 0.6716827432867392935, -1.918029732621558454 + 3.141592653589793239*I]]], [[[4, -1, 0]~, [1, -1, 0]~, [-2, -1, 0]~, [1, 1, 0]~, [10, 5, 1]~, [3, 1, 0]~, [3, 0, 0]~, [7, 2, 0]~, [-2, -1, 1]~], 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) [-1.000000000000000000, 1.000000000000000000]~ ? (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 modulo: 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);a=matrix(3,5,j,k,vvector(5,l,random()\10^8)) [[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, 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]]] ? 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, 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]]] ? 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]~ ? setrand(1);as=matrix(3,3,j,k,vvector(5,l,random()\10^8)) [[3, 13, 9, 6, 18]~ [18, 1, 20, 4, 7]~ [11, 6, 19, 10, 18]~] [[6, 17, 13, 19, 5]~ [7, 13, 4, 10, 13]~ [11, 14, 18, 0, 20]~] [[6, 17, 13, 14, 18]~ [5, 6, 20, 21, 1]~ [0, 16, 8, 7, 5]~] ? nfsmith(nf,[as,[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 - 363*x - 2663, 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) [4, 7, 1, 6, 3, 5, 2] ? permutation2num([4,7,1,6,3,5,2]) 1035 ? pf(-44,3) qfi(3, 2, 4) ? phi(257^2) 65792 ? pi 3.141592653589793239 ? b=10;a=1<1e-18,f(x),subst(F,t,x)); ? intnum(x=0,[oo,1],f(x))-Euler 0.E-96 ? intnum(x=0,[oo,1],g(x))-Euler 0.E-96 ? intnum(x=0,1,1/sqrt(x))-2 -1.4009863823182375326 E-54 ? intnum(x=[0,-1/2],1,1/sqrt(x))-2 0.E-95 ? intnum(x=0,[oo,1],sin(x)/x)-Pi/2 0.00448267113448250456172244085159836765958193607953130895411895619311247452 425300891424918944797443 ? intnum(x=0,[oo,-I],sin(x)/x)-Pi/2 0.E-96 ? intnum(x=0,[oo,-2*I],sin(2*x)/x)-Pi/2 0.E-96 ? 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 -9.36335271 E-97 ? intnum(x=0,[oo,1],sin(x)^3*exp(-x))-0.3 0.E-96 ? intnum(x=0,[oo,-I],sin(x)^3*exp(-x))-0.3 -1.335284649 E-89 ? tab=intnuminit(0,[oo,-I],m+1); ? intnum(x=0,oo,sin(x)^3*exp(-x),tab)-0.3 0.E-96 ? intnum(x=0,[oo,-I],x^2*sin(x))+2 5.618011626 E-96 ? tab=intnuminit(-1,1); ? intnum(x=-1,1,intnum(y=-sqrt(1-x^2),sqrt(1-x^2),x^2+y^2,tab),tab)-Pi/2 -1.779037015 E-94 ? \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); ? a-b -1.004064579 E-306 + 0.E-331*I ? sumnum(n=1,2,1/(n^3+n+1),tab,1)-a 1.004064579 E-306 ? c=sumnum(n=1,2,1/(n^2+1),tab,1); ? d=sumpos(n=1,1/(n^2+1)); ? d-c 1.969190365 E-306 ? sumnum(n=1,2,n^(-4/3),,1)-zeta(4/3) -2.4216544207504506114899981581969759071445497499100570634176004383007422693 6954882413244126542269381152110599476350651837206116316883640508880554373752 13154920980196906076673594248661407504915027261660100 E-107 ? tab=sumnuminit([2,-3/2]); ? sumnum(n=1,[2,-3/2],1/(n*sqrt(n)),tab,1)-zeta(3/2) -1.190414515 E-305 ? suminf(n=1,2^(-n))-1 -1.112536930 E-308 ? sumpos(n=1,2^(-n))-1 -2.781342324 E-308 ? sumnum(n=1,[2,log(2)],2^(-n),intnumstep()+1,1)-1 -1.950277237 E-305 ? 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)); ? a-b -1.390671162 E-308 ? print("Total time spent: ",gettime); Total time spent: 66492 pari-2.5.5/src/test/32/charpoly0000644000175000017500000000023711636712103014644 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^2 - 4*x Total time spent: 4 pari-2.5.5/src/test/32/extract0000644000175000017500000000574512147140047014506 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] [0 1 0] [0 0 1] [0] [1] [0, 2] [0, 2] [0, 0] Total time spent: 4 pari-2.5.5/src/test/32/nfhilbert0000644000175000017500000000043712147140047015002 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 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] Total time spent: 1288 pari-2.5.5/src/test/32/member0000644000175000017500000002607112147140047014276 0ustar billbill realprecision = 38 significant digits NF .diff: [1105, 553; 0, 1] .codiff: [1, 553/1105; 0, 1/1105] .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]]], [-33.241540277189322804630581542105218897, 33.24154027718932280 4630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0, 1, 1 , -1]] .pol: y^2 - 1105 .roots: [-33.241540277189322804630581542105218897, 33.2415402771893228046305 81542105218897] .sign: [2, 0] .r1: 2 .r2: 0 .t2: [2, -1.0000000000000000000000000000000000000; -1.0000000000000000000000 000000000000000, 552.99999999999999999999999999999999998] .zk: [1, 1/2*y - 1/2] BNF .bnf: [[2, 0; 0, 2], [1, 1, 0, 1, 0, 1, 1; 1, 0, 1, 1, 1, 0, 1], [-10.950385 405825605330267750825017937393 + 3.1415926535897932384626433832795028842*I; 10.950385405825605330267750825017937393], [8.1433720041619460221749001672695 803069 + 3.1415926535897932384626433832795028842*I, 4.4847567981443655473417 848269834687859 + 3.1415926535897932384626433832795028842*I, -1.343048075374 9138388048557277007612130, 0.E-37, 21.900770811651210660535501650035874786 + 1.8807909620000000000000000000000000000 E-37*I, 28.214835212804366445293844 147162399333 + 1.8807909620000000000000000000000000000 E-37*I, -8.7080070067 534225565968584115262030002 + 6.2831853071795864769252867665590057684*I, 4.0 716860020809730110874500836347901535 + 2.35098870200000000000000000000000000 00 E-38*I, -7.9295939339699852522139609280820644804 + 3.14159265358979323846 26433832795028841*I; -8.1433720041619460221749001672695803069 + 3.1415926535 897932384626433832795028841*I, -4.4847567981443655473417848269834687859 + 3. 1415926535897932384626433832795028842*I, 1.343048075374913838804855727700761 2130 + 3.1415926535897932384626433832795028842*I, 0.E-37, -21.90077081165121 0660535501650035874786 + 6.2831853071795864769252867665590057684*I, -28.2148 35212804366445293844147162399333 + 6.2831853071795864769252867665590057682*I , 8.7080070067534225565968584115262030002 + 3.141592653589793238462643383279 5028842*I, -4.0716860020809730110874500836347901535 + 3.14159265358979323846 26433832795028842*I, 7.9295939339699852522139609280820644804 + 4.70197740000 00000000000000000000000000 E-38*I], [[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], [ 3, [0, 2]~, 1, 1, [-1, -276; -1, 0]], [11, [8, 2]~, 1, 1, [5, 552; 2, 3]], [ 2, [2, 1]~, 1, 1, [1, 276; 1, 0]], [3, [2, 2]~, 1, 1, [0, -276; -1, 1]], [5, [1, 2]~, 2, 1, [1, 552; 2, -1]], [17, [1, 2]~, 2, 1, [1, 552; 2, -1]], [13, [1, 2]~, 2, 1, [1, 552; 2, -1]], [11, [16, 2]~, 1, 1, [-3, 552; 2, -5]]], 0 , [y^2 - 1105, [2, 0], 1105, 2, [[1, -17.12077013859466140231529077105260944 8; 1, 16.120770138594661402315290771052609448], [1, -17.12077013859466140231 5290771052609448; 1, 16.120770138594661402315290771052609448], [1, -17; 1, 1 6], [2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1 , 552]]], [-33.241540277189322804630581542105218897, 33.24154027718932280463 0581542105218897], [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.950385405825605330267750 825017937393, 1, [2, -1], [857*y + 28488]], [[-1, 0; 0, -1], [[0, 0], [0, 0] ], [[-8.1433720041619460221749001672695803069 - 3.14159265358979323846264338 32795028842*I, 8.1433720041619460221749001672695803069 - 3.14159265358979323 84626433832795028841*I], [-4.4847567981443655473417848269834687859 - 3.14159 26535897932384626433832795028842*I, 4.4847567981443655473417848269834687859 - 3.1415926535897932384626433832795028842*I]]], 0] .clgp: [4, [2, 2], [[2, 0; 0, 1], [3, 1; 0, 1]]] .cyc: [2, 2] .diff: [1105, 553; 0, 1] .codiff: [1, 553/1105; 0, 1/1105] .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]]], [-33.241540277189322804630581542105218897, 33.24154027718932280 4630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0, 1, 1 , -1]] .no: 4 .pol: y^2 - 1105 .reg: 10.950385405825605330267750825017937393 .roots: [-33.241540277189322804630581542105218897, 33.2415402771893228046305 81542105218897] .sign: [2, 0] .r1: 2 .r2: 0 .t2: [2, -1.0000000000000000000000000000000000000; -1.0000000000000000000000 000000000000000, 552.99999999999999999999999999999999998] .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, 1]~], 2; [2, [2, 1]~, 1, 1, [1, 1]~], 2], [[[[1], [[1, 0]~], [[1, 0]~], [Vecsmall([])], 1], [[2], [[-1, 0]~], [[1, -2]~], [Vecsmall([])] , Mat([1/2, -1/2])]], [[[1], [[1, 0]~], [[1, 0]~], [Vecsmall([])], 1], [[2], [[-1, 0]~], [[-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, 1; 1, 0, 1, 1, 1, 0, 1], [-10.950385 405825605330267750825017937393 + 3.1415926535897932384626433832795028842*I; 10.950385405825605330267750825017937393], [8.1433720041619460221749001672695 803069 + 3.1415926535897932384626433832795028842*I, 4.4847567981443655473417 848269834687859 + 3.1415926535897932384626433832795028842*I, -1.343048075374 9138388048557277007612130, 0.E-37, 21.900770811651210660535501650035874786 + 1.8807909620000000000000000000000000000 E-37*I, 28.214835212804366445293844 147162399333 + 1.8807909620000000000000000000000000000 E-37*I, -8.7080070067 534225565968584115262030002 + 6.2831853071795864769252867665590057684*I, 4.0 716860020809730110874500836347901535 + 2.35098870200000000000000000000000000 00 E-38*I, -7.9295939339699852522139609280820644804 + 3.14159265358979323846 26433832795028841*I; -8.1433720041619460221749001672695803069 + 3.1415926535 897932384626433832795028841*I, -4.4847567981443655473417848269834687859 + 3. 1415926535897932384626433832795028842*I, 1.343048075374913838804855727700761 2130 + 3.1415926535897932384626433832795028842*I, 0.E-37, -21.90077081165121 0660535501650035874786 + 6.2831853071795864769252867665590057684*I, -28.2148 35212804366445293844147162399333 + 6.2831853071795864769252867665590057682*I , 8.7080070067534225565968584115262030002 + 3.141592653589793238462643383279 5028842*I, -4.0716860020809730110874500836347901535 + 3.14159265358979323846 26433832795028842*I, 7.9295939339699852522139609280820644804 + 4.70197740000 00000000000000000000000000 E-38*I], [[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], [ 3, [0, 2]~, 1, 1, [-1, -276; -1, 0]], [11, [8, 2]~, 1, 1, [5, 552; 2, 3]], [ 2, [2, 1]~, 1, 1, [1, 276; 1, 0]], [3, [2, 2]~, 1, 1, [0, -276; -1, 1]], [5, [1, 2]~, 2, 1, [1, 552; 2, -1]], [17, [1, 2]~, 2, 1, [1, 552; 2, -1]], [13, [1, 2]~, 2, 1, [1, 552; 2, -1]], [11, [16, 2]~, 1, 1, [-3, 552; 2, -5]]], 0 , [y^2 - 1105, [2, 0], 1105, 2, [[1, -17.12077013859466140231529077105260944 8; 1, 16.120770138594661402315290771052609448], [1, -17.12077013859466140231 5290771052609448; 1, 16.120770138594661402315290771052609448], [1, -17; 1, 1 6], [2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1 , 552]]], [-33.241540277189322804630581542105218897, 33.24154027718932280463 0581542105218897], [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.950385405825605330267750 825017937393, 1, [2, -1], [857*y + 28488]], [[-1, 0; 0, -1], [[0, 0], [0, 0] ], [[-8.1433720041619460221749001672695803069 - 3.14159265358979323846264338 32795028842*I, 8.1433720041619460221749001672695803069 - 3.14159265358979323 84626433832795028841*I], [-4.4847567981443655473417848269834687859 - 3.14159 26535897932384626433832795028842*I, 4.4847567981443655473417848269834687859 - 3.1415926535897932384626433832795028842*I]]], [0, [Mat([[16, -1]~, 1]), Ma t([[-137, -8]~, 1])]]] .clgp: [4, [2, 2]] .cyc: [2, 2] .diff: [1105, 553; 0, 1] .codiff: [1, 553/1105; 0, 1/1105] .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]]], [-33.241540277189322804630581542105218897, 33.24154027718932280 4630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0, 1, 1 , -1]] .no: 4 .pol: y^2 - 1105 .roots: [-33.241540277189322804630581542105218897, 33.2415402771893228046305 81542105218897] .sign: [2, 0] .r1: 2 .r2: 0 .t2: [2, -1.0000000000000000000000000000000000000; -1.0000000000000000000000 000000000000000, 552.99999999999999999999999999999999998] .zk: [1, 1/2*y - 1/2] RNF .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]]], [-33.241540277189322804630581542105218897, 33.24154027718932280 4630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0, 1, 1 , -1]] .pol: 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])] .mod: 96889010407 .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 .j: 6128487/10351 .omega: [2.7807400137667297710631976271813584994, 1.390370006883364885531598 8135906792497 - 1.0687497763561930661592635474375038788*I] .eta: [3.1096482423243803285501491221965830079 + 2.3509887020000000000000000 000000000000 E-38*I, 1.5548241211621901642750745610982915040 + 1.06437474521 02737569438859937299427442*I] .roots: [-1.6189099322673713423780009396072169751, -0.3155450338663143288109 9953019639151248 - 2.0925470969119586079816894466366945829*I, -0.31554503386 631432881099953019639151248 + 2.0925470969119586079816894466366945829*I]~ ELLQp .a1: 1 + O(11^2) .a2: 2 + O(11^2) .a3: 3 + O(11^2) .a4: 4 + O(11^2) .a6: 5 + O(11^2) .b2: 9 + O(11^2) .b4: 11 + O(11^2) .b6: 7 + 2*11 + O(11^2) .b8: 2 + 3*11 + O(11^2) .c4: 4 + 5*11 + O(11^2) .c6: 3 + 7*11 + O(11^2) .disc: 5*11 + O(11^2) .j: 4*11^-1 + O(11^0) .roots: [9 + O(11^2)] .tate: [6 + 8*11 + O(11^2), 0, 3*11 + O(11^2)] .w: 1 + 3*11 + O(11^2) SMALLELL .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 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] Total time spent: 60 pari-2.5.5/src/test/32/graph0000644000175000017500000000565112147140053014126 0ustar billbill echo = 1 (on) ? gettime;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]) ? getheap [9, 151] ? print("Total time spent: ",gettime); Total time spent: 8 pari-2.5.5/src/test/32/quadclassunit0000644000175000017500000004165412147140047015713 0ustar billbill? gettime; ? test(D)=for(d=D,D+10^3,if(!isfundamental(d),next);print(d," ",quadclassuni t(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] ? print("Total time spent: ",gettime); Total time spent: 6324 pari-2.5.5/src/test/32/list0000644000175000017500000000102612147140047013773 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 *** at top-level: ...;listput(L,1);listpop(L);listpop(L) *** ^---------- *** listpop: empty list in listpop. [List([0])] List([10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]) List([10, 9, 8, 7, 6, 5]) List([1, y + 1]) List([y, x]) List([y, y*x]) 107 Total time spent: 48 pari-2.5.5/src/test/32/quad0000644000175000017500000000002711636712103013752 0ustar billbill1 Total time spent: 12 pari-2.5.5/src/test/32/ell0000644000175000017500000000417012147140047013577 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 163663 121661 1 494 [4, [2, 2], [[2147484185, 0], [0, 0]]] [0, 0.25384186085591068433775892335090946106] [1, 0.30599977383405230182048368332167647431] [2, 1.5186330005768535404603852157894440351] [3, 10.391099400715804138751850510360916947] [5, 9997.0334671722554999496820788093287993] 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 x^-2 + 31/15*x^2 + 2501/756*x^4 + 961/675*x^6 + 77531/41580*x^8 + O(x^9) [-1, -2*w] Total time spent: 4896 pari-2.5.5/src/test/32/subst0000644000175000017500000000004712167755167014203 0ustar billbillY/x x + 1 0 O(x^2) Total time spent: 4 pari-2.5.5/src/test/32/mat0000644000175000017500000000043412147140047013603 0ustar billbill *** at top-level: Mat([1])+matrix(0,1) *** ^------------ *** _+_: impossible addition t_MAT + t_MAT. *** at top-level: 1/matrix(2,2,i,j,Mod( *** ^-------------------- *** _/_: non invertible matrix in gauss Total time spent: 4 pari-2.5.5/src/test/32/galois0000644000175000017500000001454312212130255014277 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.5.5/src/test/32/trans0000644000175000017500000006542012147140047014157 0ustar billbill realprecision = 2003 significant digits (2000 digits displayed) echo = 1 (on) ? gettime;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,20) 3.1415926535897932384626433833 ? 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 ? 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 - 5.94091115 E-2 13*I ? 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 ? getheap [60, 6760] ? print("Total time spent: ",gettime); Total time spent: 60 pari-2.5.5/src/test/32/polyser0000644000175000017500000001466112147140047014526 0ustar billbill echo = 1 (on) ? gettime;apol=x^3+5*x+1 x^3 + 5*x + 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))*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] ? factorpadic(apol,7,8,1) [(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] ? 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 663382582902335604 + 0.84813118358634026680538906224199030918*I, -0.67063790 319207539268663382582902335604 - 0.84813118358634026680538906224199030918*I, -0.35481882329952371381627468235580237078 + 1.39980287391035466982975228340 62081965*I, -0.35481882329952371381627468235580237078 - 1.399802873910354669 8297522834062081965*I]~ ? polroots(x^4-1000000000000000000000,1) [-177827.94100389228012254211951926848447 + 0.E-38*I, 177827.941003892280122 54211951926848447 + 0.E-38*I, 0.E-66 + 177827.941003892280122542119519268484 47*I, 0.E-66 - 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 ? getheap [58, 7208] ? print("Total time spent: ",gettime); Total time spent: 8 pari-2.5.5/src/test/32/err0000644000175000017500000000171512147140047013615 0ustar billbill *** at top-level: g(10) *** ^----- *** in function g: for(i=-N,N,f(i)) *** ^----- *** in function f: 1/x *** ^-- *** _/_: division by zero *** at top-level: f(Mat(0),Col(0)) *** ^---------------- *** in function f: matsolve *** ^-------- *** matsolve: non invertible matrix in gauss *** at top-level: (matsolve)(Mat(0),Col *** ^-------------------- *** matsolve: non invertible matrix in gauss *** at top-level: g(I) *** ^---- *** in function g: [x.foo] *** ^---- *** in member function foo: 1/(1+a^2) *** ^-------- *** _/_: division by zero *** at top-level: (x->1/x)(0) *** ^---------- *** in anonymous function: 1/x *** ^-- *** _/_: division by zero Total time spent: 24 pari-2.5.5/src/test/32/number0000644000175000017500000001253612147140047014320 0ustar billbill echo = 1 (on) ? gettime;addprimes([nextprime(10^9),nextprime(10^10)]) [1000000007, 10000000019] ? bestappr(Pi,10000) 355/113 ? bezout(123456789,987654321) [-8, 1, 9] ? bigomega(12345678987654321) 8 ? binomial(1.1,5) -0.0045457500000000000000000000000000000001 ? 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)]] ? getheap [87, 2719] ? print("Total time spent: ",gettime); Total time spent: 28 pari-2.5.5/src/test/32/ideal0000644000175000017500000000076312147140047014105 0ustar billbill[;] [[1]~, [0]~] *** at top-level: idealaddtoone(Q,[1,[ *** ^-------------------- *** idealaddtoone: not an integer matrix in idealaddmultoone. *** at top-level: ideallog(Q,2,idealst *** ^-------------------- *** ideallog: 2 not coprime to [2, [2]~, 1, 1, 1] in zlog_pk. *** at top-level: idealstar(Qi,matdiag *** ^-------------------- *** idealstar: non coprime ideals in idealaddtoone. [1/2 0] [0 1/2] Total time spent: 0 pari-2.5.5/src/test/32/krasner0000644000175000017500000001273211636712103014473 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]] Total time spent: 5691 pari-2.5.5/src/test/32/objets0000644000175000017500000000415312147140047014312 0ustar billbill echo = 1 (on) ? gettime;+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 698368 + 0.18258225455744299269398828369501930574*I, 0.460202188254280606994 79112458168698368 - 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) [4, 7, 1, 6, 3, 5, 2] ? permtonum([4,7,1,6,3,5,2]) 1035 ? 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 modulo: Mod(131, 49649). ? getheap [59, 808] ? print("Total time spent: ",gettime); Total time spent: 0 pari-2.5.5/src/test/32/random0000644000175000017500000000077712147140047014314 0ustar billbillMod(0, 3) 0 [[1, 1], 1] 1387580271*a^2 + 3706911745*a + 1312695376 [[1236160327*a^2 + 1145818671*a + 2609978921, 2562752193*a^2 + 4076017442*a + 2988795632], 1] 3728756628529537051*a^2 + 6422638149855794201*a + 15580190479849132290 [[6186193757377372050*a^2 + 2212948305693001488*a + 15939615155660301108, 98 88790390411102399*a^2 + 11856256701935116461*a + 9430491011372318031], 1] 0.5097952582783875010084034483 Mod(1, 7)*x^5 + Mod(6, 7)*x^4 + Mod(4, 7)*x^3 + Mod(3, 7)*x^2 + Mod(3, 7)*x Total time spent: 8 pari-2.5.5/src/test/32/ploth0000644000175000017500000000663312147140047014157 0ustar billbill echo = 1 (on) ? \p19 realprecision = 19 significant digits ? gettime;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)], *** ^-------------------- *** multi-curves cannot be plot recursively. ? 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]) ? print("Total time spent: ",gettime); Total time spent: 28 pari-2.5.5/src/test/32/galoisinit0000644000175000017500000000115112147140047015161 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: Not a Galois group in a Galois related function. [x]~ [-x, x]~ [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, 4, 5, 1, 0, 0]~] Mod(x^4 + x^2, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1) Total time spent: 5684 pari-2.5.5/src/test/32/aurifeuille0000644000175000017500000000031311636712103015324 0ustar billbill2818034765526617919871 13851033738067865242961762796990508103341 2818034765526617919871 48975219025052205901 288943522443730350379346314566889 73194743542229 97 13 818201 13 1741 31 Total time spent: 16 pari-2.5.5/src/test/32/factorint0000644000175000017500000000022112147140047015005 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: 12 pari-2.5.5/src/test/32/round0000644000175000017500000000002612212110474014140 0ustar billbill1 Total time spent: 4 pari-2.5.5/src/test/32/bnfinit0000644000175000017500000000000011636712103014440 0ustar billbillpari-2.5.5/src/test/32/qf0000644000175000017500000000014212147140047013424 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] Total time spent: 4 pari-2.5.5/src/test/32/debugger0000644000175000017500000000203312147140047014603 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+s tep,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 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) *** ^--- *** _/_: division by zero *** Break loop: type 'break' to go back to GP break> [p,i] [120, 1] break> break ? print("Total time spent: ",gettime); Total time spent: 0 pari-2.5.5/src/test/32/rnf0000644000175000017500000000525512147140047013615 0ustar billbill[[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [[6, 0; 0, 6], [6, 0; 0, 6], [6, 0; 0, 6], [6, 0; 0, 6]]] [] [[1, 0, 0, 0, 0, [-227930/1129, -1385/1129]~, [-456265/1129, -1960/1129]~, [ -2959567/21451, -22793/21451]~, [-5924397/21451, -35060/21451]~; 0, 1, 0, 0, 0, [-52431/1129, 994/1129]~, [-104954/1129, 2172/1129]~, [-3793695/21451, - 27715/21451]~, [-7594135/21451, -41940/21451]~; 0, 0, 1, 0, 0, [270226/1129, 339/1129]~, [540931/1129, -280/1129]~, [2097817/21451, 8762/21451]~, [41993 58/21451, 10076/21451]~; 0, 0, 0, 1, 0, [3065/1129, 644/1129]~, [6136/1129, 1276/1129]~, [989334/21451, 16275/21451]~, [1980435/21451, 29016/21451]~; 0, 0, 0, 0, 1, [-227131/1129, -725/1129]~, [-454665/1129, -644/1129]~, [-30096 94/21451, 13108/21451]~, [-6024708/21451, 36856/21451]~; 0, 0, 0, 0, 0, [-56 4/1129, -1/1129]~, -1, [-5/21451, 10/21451]~, [-10/21451, 20/21451]~; 0, 0, 0, 0, 0, [1/1129, -2/1129]~, [2/1129, -4/1129]~, [8/21451, -16/21451]~, [16/ 21451, -32/21451]~; 0, 0, 0, 0, 0, 0, 0, [-10722/21451, -7/21451]~, [-21463/ 21451, 24/21451]~; 0, 0, 0, 0, 0, 0, 0, [1/21451, -2/21451]~, [2/21451, -4/2 1451]~], [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, 0; 0, 1/3], [1/3, 0; 0, 1/3], [1/3, 0; 0, 1/3]], [64 87513772307278389925284499624661, 0; 0, 6487513772307278389925284499624661], 6487513772307278389925284499624661] [[Mat(861), [1]], [480, [120, 2, 2], [[-287240]~, [-245960]~, [-494500]~]], [2, 0, 1; 0, 2, 1; 0, 0, 1]] [0, [[1, 0, 0; 0, 1, 0; 0, 0, 1], [[1, 0; 0, 1], [1, 0; 0, 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 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) Total time spent: 212 pari-2.5.5/src/test/32/zn0000644000175000017500000000016512147140047013452 0ustar billbillMod(5, 9223372036854775837) *** _^_: Warning: Mod(a,b)^n with n >> b : wasteful. Mod(84, 148) Total time spent: 20 pari-2.5.5/src/test/32/printf0000644000175000017500000002664012141040641014324 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 Total time spent: 8 pari-2.5.5/src/test/32/exact00000644000175000017500000000124711636712103014211 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.5.5/src/test/32/subfields0000644000175000017500000037653312147140047015022 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 - 192*x^2 + 10920*x - 73888, 27/3136*x^8 - 5/32*x^7 + 3135/3136*x^ 6 - 1007/392*x^5 - 83/784*x^4 + 1485/98*x^3 + 3083/784*x^2 + 701/196*x + 34/ 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]] 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 - 2796*x^2 - 960*x + 64, -73984679474629670714490817033054 1403783036378321220562733077/16459531015853707400528673626339078612702888208 065089236014302*x^26 - 22109932951379204001536997211773021233754207028431607 12207137/90527420587195390702907704944864932369865885144357990798078661*x^25 + 7744520170075936726930825115050660035652030327315379025370168609/14484387 29395126251246523279117838917917854162309727852769258576*x^24 + 828482906012 3899673354193629984574355737519289228087543949666801/14484387293951262512465 23279117838917917854162309727852769258576*x^23 - 359012410291184553542546274 985346565451231093312484340564713122561/144843872939512625124652327911783891 7917854162309727852769258576*x^22 - 5263552140643076104662870410022380842737 09423917420752758848566155/1448438729395126251246523279117838917917854162309 727852769258576*x^21 + 42140741641450187741033304547750887680754020734447545 15666988968027/7242193646975631256232616395589194589589270811548639263846292 88*x^20 + 685333941994204545917666687114508041352829458300155523409117259047 /65838124063414829602114694505356314450811552832260356944057208*x^19 - 10691 1345913162890145797530748166151719319481766399539290295124370257/14484387293 95126251246523279117838917917854162309727852769258576*x^18 - 220699529162793 896856370984197801378507797376158324629810580186498873/144843872939512625124 6523279117838917917854162309727852769258576*x^17 + 7150816217488630358962577 30347336007514096632125143483060169924296217/1448438729395126251246523279117 838917917854162309727852769258576*x^16 + 23242245686525056559772267929522331 627971575613709400185272082977721/204005454844383979048806095650399847594063 96652249688067172656*x^15 - 231312360166809052354218084484994024187857914237 2464102564115124139141/14484387293951262512465232791178389179178541623097278 52769258576*x^14 - 585657384667769513617702958658304558999174768277310421471 9002354121491/14484387293951262512465232791178389179178541623097278527692585 76*x^13 + 365118083239442569774045110157815724620568954599750606728744369603 8813/1448438729395126251246523279117838917917854162309727852769258576*x^12 + 10040426520561184085992260635787732864328665489520074163406248596214953/144 8438729395126251246523279117838917917854162309727852769258576*x^11 - 1141881 976159943056150352420584376105638987469781569823827491087714737/724219364697 563125623261639558919458958927081154863926384629288*x^10 - 19418402921569858 56042966823843091035965664640434668187482417279631473/3621096823487815628116 30819779459729479463540577431963192314644*x^9 - 4058602457148394615990722029 4542873850923622637376408267704565530984/90527420587195390702907704944864932 369865885144357990798078661*x^8 + 108204590670924892850536714401337280605429 1746075595735961248749508317/72421936469756312562326163955891945895892708115 4863926384629288*x^7 + 88613800370254680411875384101351877818551329488074366 4803293008769151/14484387293951262512465232791178389179178541623097278527692 58576*x^6 + 1269141287869800364601057824070219376621096840567842007072173038 733/20400545484438397904880609565039984759406396652249688067172656*x^5 - 979 9925291232410467649476579009759547499077607129326386012443315269/72421936469 7563125623261639558919458958927081154863926384629288*x^4 - 16587312092935826 07061161341066424240216534357816117719110794086563/3621096823487815628116308 19779459729479463540577431963192314644*x^3 - 4169594195115335915572156711431 8027713659987217016395377055931636/90527420587195390702907704944864932369865 885144357990798078661*x^2 - 565811499675739577358575044276217404544607786020 598769176544051/905274205871953907029077049448649323698658851443579907980786 61*x + 46945163889986656942312064244366240832320064800593433556330540/905274 20587195390702907704944864932369865885144357990798078661], [x^3 - 2256*x^2 + 6096*x + 64, -19417089345059614340124298831250860157099952726892251/7705742 02417890161481916508657135480583189210820336*x^26 + 465261347703887731979726 777504133076469790749716419/700522002198081964983560462415577709621081100745 76*x^25 + 145546216272635060505776677527078053207287212099723363/48160887651 118135092619781791070967536449325676271*x^24 + 60951131256604505242573840398 7685164063245222472298727/77057420241789016148191650865713548058318921082033 6*x^23 - 110318280383775639376861574755712333778850601164726902531/770574202 417890161481916508657135480583189210820336*x^22 - 35764561073596826122555693 587416304111300918329291915265/385287101208945080740958254328567740291594605 410168*x^21 + 2698676556819145207899673118695897987172753535814855959363/770 574202417890161481916508657135480583189210820336*x^20 + 25353007879667576538 99707912201660658080677991096347496733/7705742024178901614819165086571354805 83189210820336*x^19 - 184500421281399807210404136633504323137224986694398491 37367/385287101208945080740958254328567740291594605410168*x^18 - 38273857003 87620146348706655911003203606860072819608162375/7005220021980819649835604624 1557770962108110074576*x^17 + 1421780866681070754078479220870244992910381109 02822453518015/385287101208945080740958254328567740291594605410168*x^16 + 49 32957987456895133578400975358311763965145004079263946901/1085315778053366424 6224176178269513811030833955216*x^15 - 7580219379619366487256640258936518160 0247079699279904970949/48160887651118135092619781791070967536449325676271*x^ 14 - 1418925692264398346905600318235468470940294544244297103895783/770574202 417890161481916508657135480583189210820336*x^13 + 29492683066280706369209501 36227355126808364474772530622119857/7705742024178901614819165086571354805831 89210820336*x^12 + 166589581259622181167910161703445645044551838284229175440 32/4378262513738012281147252890097360685131756879661*x^11 - 9905457849459218 59397562859484696191953405596548533237819111/1926435506044725403704791271642 83870145797302705084*x^10 - 157793499488740516342739786938798832550021353883 9953957172237/385287101208945080740958254328567740291594605410168*x^9 + 2516 727370631008693858453403744864813447233354335460822902795/770574202417890161 481916508657135480583189210820336*x^8 + 168807157196505177595021303258144303 674164728470637182661851/70052200219808196498356046241557770962108110074576* x^7 - 518331865777061706687804543605794467151246150122922616485461/770574202 417890161481916508657135480583189210820336*x^6 - 177627011913966146409023879 9174385930766842582827745181371/27132894451334160615560440445673784527577084 88804*x^5 - 3795395413907166661496173345979920804875647669966430644559/48160 887651118135092619781791070967536449325676271*x^4 + 935037583110078417918059 907483691589942806970032644103842/481608876511181350926197817910709675364493 25676271*x^3 + 207029474816692518951026699800427111617432833336068658906/481 60887651118135092619781791070967536449325676271*x^2 + 7357964953188324444369 967201461211123383988457557368072/481608876511181350926197817910709675364493 25676271*x - 296542410803660849197540276703255503397498629122175636/48160887 651118135092619781791070967536449325676271], [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]] Total time spent: 15068 pari-2.5.5/src/test/32/nf0000644000175000017500000000611112147140047013423 0ustar billbill realprecision = 38 significant digits [85997496, [42998748, 2], [[408188227, 99620635; 0, 1], [2, 1; 0, 1]]] 12.340047278667903334059769086970462174 4.1894250945222025884896456921310573061 20915648110955829231381594293324156411897455346679838307589120000 571459344155975480004612560667633185714077696 [54898, [54898], [[383, 102; 0, 1]]] [26, [26], [[19, 14, 18, 6; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]]] [1, [], []] *** zetakinit: Warning: non-monic polynomial. Result of the form [nf,c]. *** zetakinit: Warning: non-monic polynomial. Change of variables discarded. 20/3 -5 13 -1 1024/243 -1 31 15853839 (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]~ [7/3, 2, 3, 4, 5]~ [1/3, 0, 0, 0, 0]~ [-2, 0, 0, 0, 0]~ [2, 1, 1, 0, 0]~ [0, 2, 3, 4, 5]~ [13/3, 1, 1, 0, 0]~ [2, 1, 1, 0, 0]~ [6, 2, 2, 0, 0]~ [4, 3, 4, 4, 5]~ [7/3, 2, 3, 4, 5]~ [0, 2, 3, 4, 5]~ [4, 3, 4, 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]~ [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]~ [-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]~ [1249690/15853839, -222317/5284613, 39600/5284613, -477392/15853839, 434/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]~ [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]~ [-1, 0, 0, 0, 0]~ [1, 0, 0, 0, 0]~ [1, 0, 0, 0, 0]~ [0, 0, 0, 0, 0]~ [2, 1, 1, 0, 0]~ [-3, -1, -1, 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]~ [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]~] [[-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, 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]~] [[0, 0, 0, 0, 0]~, [3, 1, 1, 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]~] [[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/3, 0, 0, 0, 0]~ [0, 0, 0, 0, 0]~ [-4, -1, -1, 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]~ [3, 1, 1, 0, 0]~ [-1/3, -2/3, 1/3, 0, -1/3]~ [0, 0, 0, 0, 0]~ [-6, -2, 1, 2, 1]~ [0, 0, 0, 0, 0]~ [16/9, 0, 0, 0, 0]~ [-4/3, 0, 0, 0, 0]~ [4, 4/3, 4/3, 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]~ [-1, -2, -3, -4, -5]~ [4, 4/3, 4/3, 0, 0]~ [-3, -1, -1, 0, 0]~ [13, 5, 6, 2, 1]~ [-58, -42, 23, 27, 17]~ [4/3, 8/3, 4, 16/3, 20/3]~ [-1, -2, -3, -4, -5]~ [-58, -42, 23, 27, 17]~ [-1071, -384, -251, -155, 20]~ [1] Total time spent: 2112 pari-2.5.5/src/test/32/ellweilpairing0000644000175000017500000001464512167755161016055 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, 112, [114]] [1, 126, [18, 6]] [156, 1, [12, 12]] [1, 1, [180]] [1, 1, [192]] [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: 84 pari-2.5.5/src/test/32/program0000644000175000017500000000766712147140047014510 0ustar billbill echo = 1 (on) ? gettime;alias(ln,log) ? ln(2) 0.69314718055994530941723212145817656808 ? 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] ? getheap [4, 37] ? getrand Vecsmall([-1972095278, 1417909247, -213878183, 815482895, -989924416, -28085 2195, 1575048288, -1054030805, 904602835, -582553908, 1381085973, -428288569 , 1270288356, 1766389265, -1339971786, -1213402920, 785563966, -57938986, -2 143243955, 1821221641, 1519700965, -1312988473, 1708126502, -729724372, -435 83276, -911125826, -210211422, -1086538876, -106058874, -1930892778, 1271738 374, 1832331804, -275722414, 921850693, 1299470328, 2103129813, 178370729, 1 633435720, 1950529697, -392224345, -1630152212, -1700961878, 1639527014, 190 4571724, -1935245990, -200728709, 1503110237, -1077030802, -2128477667, -188 6771698, 2068700198, 1335558872, -40704575, -1716288474, -428076490, 3275897 60, -2055794902, -2107417159, 1852929442, -1923393949, 479083913, 1835012793 , -719906640, 1133990138, 1124375894, 1385717657, -665788180, 73266511, 1948 243392, 1562522998, -1353506787, -1188406992, 187772291, 943797914, -5047985 64, -1150577858, -211794460, -512521335, 802669308, 175139474, -1806003951, -1228743455, 846421529, -501783503, 44081230, -239366181, -28827595, -177724 6515, -1618494939, -740494678, -1793051392, -949430766, 1480035755, 70181632 6, -1773856301, -984413887, 556302438, 1562175626, 181666477, 2104619075, 68 9010199, -1035475640, -1274881894, -466135931, -1618924136, 1300365442, -147 8158199, -1894392966, -680598018, -1806566044, -1657930315, -1759975568, -16 24736741, -1355350182, -691417014, 77750120, 1670442608, -1018757566, -17097 99837, -1039970767, 60357790, 272658424, 1813518504, -405967781, 74175307, - 102997450, -281974336, -254214701, 127, 702552219]) ? getstack 104 ? 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 ? setrand(10) ? 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(realprecision,28) ? 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" "l og(p)/log(q)))); 50 1.561229126903099279206171726 100 1.601335375590875348711141031 150 1.606915548673659127523394774 200 1.618659998991528481508175176 250 1.626284706204746765086080989 300 1.627822776845103001192024532 350 1.632105905172986668189652273 400 1.632424285532931448171405619 ? install(addii,GG) ? addii(1,2) 3 ? kill(addii) ? getheap [23, 3317] ? print("Total time spent: ",gettime); Total time spent: 24 pari-2.5.5/src/test/32/intformal0000644000175000017500000000003611636712103015013 0ustar billbill-Y*A + Y Total time spent: 30 pari-2.5.5/src/test/32/resultant0000644000175000017500000007242312147140047015052 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 Total time spent: 7564 pari-2.5.5/src/test/32/minim0000644000175000017500000000003611706644717014146 0ustar billbill1 1 78 77 Total time spent: 0 pari-2.5.5/src/test/32/linear0000644000175000017500000003662612147140047014310 0ustar billbill echo = 1 (on) ? gettime;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],-2) [Mod(6, 7), Mod(5, 7)]~ ? 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.2833494518006402717978106547571267252 1 0.283349451800640271797810654757 12672521] [-0.14167472590032013589890532737856336261 -2 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,3) [[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]) [3] ? matimagecompl(Pi*[1,3,5;2,4,6;3,5,7]) [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 840494514780771076350, 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] ? aset=Set([5,-2,7,3,5,1]) ["-2", "1", "3", "5", "7"] ? bset=Set([7,5,-5,7,2]) ["-5", "2", "5", "7"] ? setintersect(aset,bset) ["5", "7"] ? setisset([-3,5,7,7]) 0 ? setminus(aset,bset) ["-2", "1", "3"] ? setsearch(aset,3) 3 ? setsearch(bset,3) 0 ? setunion(aset,bset) ["-2", "-5", "1", "2", "3", "5", "7"] ? 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]],,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] ? getheap [104, 10479] ? print("Total time spent: ",gettime); Total time spent: 8 pari-2.5.5/src/test/tune.c0000644000175000017500000004271212147140047013777 0ustar billbill/* $Id$ 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 Montgomery 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_invMontgomery(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_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_pow(speed_param *s) { GEN x = rand_Flx(degpol(s->x)-1, s->l); TIME_FUN( Flxq_pow(x, utoipos(s->l), s->x, 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_invMontgomery(s->x, s->p)); } 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_pow(speed_param *s) { GEN x = rand_NFpX(degpol(s->x)-1); TIME_FUN( FpXQ_pow(x, s->p, s->x, 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_INVMONTGOMERY_LIMIT),t_NFlx,10,0, speed_Flx_inv,0.05}, {0, var(Flx_REM_MONTGOMERY_LIMIT),t_NFlx,10,0, speed_Flx_rem,0.05}, {0, var(Flx_POW_MONTGOMERY_LIMIT),t_NFlx,10,0, speed_Flxq_pow}, {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_INVMONTGOMERY_LIMIT), t_NFpX,10,0, speed_FpX_inv,0.05}, {0, var(FpX_REM_MONTGOMERY_LIMIT),t_NFpX,10,0, speed_FpX_rem,0.05}, {0, var(FpX_POW_MONTGOMERY_LIMIT),t_NFpX,10,0, speed_FpXQ_pow}, {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(talker, "Fatal error: new reps bad: %.2f\n", 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(talker,"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\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; 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) diag("Setting %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; 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("usage: tune [-t] [-s step_factor] [-p mod] [-u unittime] var1 var2 ...\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); (void) init_modular(&DFLT_mod); 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 += 2; 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.5.5/src/test/in/0000755000175000017500000000000012212611624013255 5ustar billbillpari-2.5.5/src/test/in/idealramgroups0000644000175000017500000000111512141040641016210 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=bnfinit(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)] pari-2.5.5/src/test/in/nfields0000644000175000017500000001010512147140047014624 0ustar billbilldefault(realprecision,38); \e \\ Initialisations diverses gettime; p2=Pol([1,3021,-786303,-6826636057,-546603588746,3853890514072057]) fa=[11699,6;2392997,2;4987333019653,2] setrand(1);a=matrix(3,5,j,k,vectorv(5,l,random\10^8)); setrand(1);as=matrix(3,3,j,k,vectorv(5,l,random\10^8)); nfpol=x^5-5*x^3+5*x+25; nf=nfinit(nfpol) nfinit(nfpol,2) nfinit(nfpol,3) nf3=nfinit(x^6+108); nf4=nfinit(x^3-10*x+8) setrand(1);bnf2=bnfinit(y^3-y-1);nf2=bnf2[7]; setrand(1);bnf=bnfinit(x^2-x-57,,[0.2,0.2]) setrand(1);bnfinit(x^2-x-100000,1) \p19 setrand(1);sbnf=bnfcompress(bnfinit(x^3-x^2-14*x-1)) \p38 bnr=bnrinit(bnf,[[5,3;0,1],[1,0]],1) rnfinit(nf2,x^5-x-2) \\ bnfcertify(bnf) setrand(1);bnfinit(x^2-x-100000,1).fu setrand(1);bnfinit(x^4+24*x^2+585*x+1791,,[0.1,0.1]) bnrconductor(bnf,[[25,13;0,1],[1,1]]) bnrconductorofchar(bnr,[2]) \\ bnfdecodemodule(bnf, \\ bnfisintnorm \\ bnfisnorm bnfisprincipal(bnf,[5,1;0,1],0) bnfisprincipal(bnf,[5,1;0,1]) \\ bnfissunit bnfisunit(bnf,Mod(3405*x-27466,x^2-x-57)) \p19 bnfinit(sbnf) \p38 bnfnarrow(bnf) bnfsignunit(bnf) \\ bnfsunit(bnf, bnr2=bnrinit(bnf,[[25,13;0,1],[1,1]],1) 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(nf4,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) \\ idealchinese idealcoprime(nf,idx,idx) idealdiv(nf,idy,idt) idealdiv(nf,idx2,idx,1) idealfactor(nf,idz) idealhnf(nf,vp[2],3) ideallist(bnf,20) \\ ideallistarch 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) \\ nffactormod 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,[as, [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) \\ \\ rnfalgtobasis p=x^5-5*x+y; aa=rnfpseudobasis(nf2,p) rnfbasis(bnf2,aa) \\ rnfbasis \\ rnfcharpoly \\ rnfdedekind \\ rnfdet rnfdisc(nf2,p) \\ rnfeltabstorel \\ rnfeltdown \\ rnfeltreltoabs \\ rnfeltup rnfequation(nf2,p) rnfequation(nf2,p,1) rnfhnfbasis(bnf2,aa) \\ rnfidealabstorel \\ rnfidealdown \\ rnfidealhnf \\ rnfidealmul \\ rnfidealnormabs \\ rnfidealnormrel \\ rnfidealreltoabs \\ rnfidealtwoelt \\ rnfidealup rnfisfree(bnf2,aa) \\ rnfisnorm \\ rnflllgram \\ rnfpolred 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.5.5/src/test/in/rnfkummer0000644000175000017500000000266411636712103015221 0ustar billbilldefault(realprecision,38); gettime; 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.5.5/src/test/in/nffactor0000644000175000017500000002533512147140047015015 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)) factor(Mod(y,y^2+1)*x^2 + y) 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,1)]),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 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 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 nffactor(3*y^2+1, 3*x^2+1) nfroots(3*y^2+1, 3*x^2+1) \\ Bug #1207 nffactor(t^6-6*t^5-3298534883316*t^4+13194139533310*t^3+3626777458830693384585198*t^2-7253554917667983838937052*t-1329227995784915872903826851489644559,x^3-3) \\ Bug #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)))) pari-2.5.5/src/test/in/rfrac0000644000175000017500000000170612147140047014304 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 ]; V = M^-1 * [ 'u, 'v, 'w ]~; A = V[1]; B = V[2]; C = V[3]; X = A^2 + B^2 + C^2; Y = A*B + A*C + B*C; Z = 'u^2 - 2*Y; [X == Z,X - Z] pari-2.5.5/src/test/in/select0000644000175000017500000000022611636712103014462 0ustar billbillselect(isprime, vector(50,i,i^2+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]) pari-2.5.5/src/test/in/apply0000644000175000017500000000023611636712103014331 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, List([1,2,3,4])) L = List([Mod(1,3), Mod(2,4)]); apply(lift, L) pari-2.5.5/src/test/in/stark0000644000175000017500000000170612147140047014333 0ustar billbillgettime; allocatemem(20*10^6) v=[321,520,577,840,904,1009,1129,1229,1297,1509,1901,1937,2305,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-12*y-1,[5,y+1]], [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.5.5/src/test/in/multivar-mul0000644000175000017500000000074112147140047015643 0ustar billbill/* Multivariable Laurent polynomial bug finding */ /* 05 Jul 2007 Michael Somos */ x;y;z; /* This is a term of a polynomial in x */ t(n)=x^max((n-1)\2,0)/if(n<1,1,if(n%2,y,z)); /* Attempt to multiply two polynomials in x */ {f(N,M,v,w)= t1=sum(n=1,#v,t(v[n]),x^N); t2=sum(n=1,#w,t(w[n]),x^M); trap(, return(1), t1*t2); 0; } {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("("t1")*("t2") ",[N,M],v,w)),2),2); } doit(9,9); pari-2.5.5/src/test/in/round40000644000175000017500000023316012147140047014423 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] ]; } for (j = 1, #v, print (j, "\tdisc = ", nfdisc(Pol(v[j]), 1))); \\ regression cases: nfdisc(x^64+2^16,1) { 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,1) } { \\ #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,1) } { 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) } pari-2.5.5/src/test/in/analyz0000644000175000017500000000023411636712103014500 0ustar billbilldefault(realprecision,38); \e gettime; 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)); getheap pari-2.5.5/src/test/in/ellsea0000644000175000017500000000302612147140047014451 0ustar billbill{ trap("talker",print("this test requires the package seadata");quit(), 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])); pari-2.5.5/src/test/in/ffisom0000644000175000017500000001311112147140047014463 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,Mod(1,13)*(x^4+2*x^2+2*x+1),Mod(1,13)*(x^4+2*x^3+2*x^2+1)); fptest(131,Mod(1,131)*x^10+Mod(126,131)*x^5+Mod(78,131),Mod(1,131)*x^10+Mod(128,131)*x^5+Mod(70,131)); fptest(11,Mod(1,11)*x^3+Mod(2,11)*x^2+Mod(6,11)*x+Mod(7,11),Mod(1,11)*x^3+Mod(5,11)*x^2+Mod(3,11)*x+Mod(6,11)); fptest(1009,Mod(1,1009)*(x^17+x+25),Mod(1,1009)*(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,Mod(1,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),Mod(1,1009)*(x^16+11)); fptest(1009,Mod(1,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),Mod(1,1009)*(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)*Mod(1,23),Mod(1,23)*(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,Mod(1,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),Mod(1,10007)*(x^30+x+2)); fptest(67108879,Mod(1,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),Mod(1,67108879)*(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,Mod(1,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),Mod(1,11)*(x^11+10*x+1)); fptest(7,Mod(1,7)*(x^14+x+4),Mod(1,7)*(x^14+5*x^8+5*x^7+x^2+2*x+5)); fptest(5,Mod(1,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),Mod(1,5)*(x^30+x^3+x+3)); fptest(7,Mod(1,7)*(x^35+2*x^2+x+6),Mod(1,7)*(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,Mod(1,2)*(x^4+x+1),Mod(1,2)*(x^4+x^3+1)); fptest(5,Mod(1,5)*(x^25+2*x^3+3*x+2),Mod(1,5)*(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,Mod(1,3)*(x^18+x^3+2*x+1),Mod(1,3)*(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,Mod(1,2)*(x^20+x^3+1),Mod(1,2)*(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,Mod(1,2)*(x^8+x^4+x^3+x+1),Mod(1,2)*(x^8+x^6+x^5+x^3+1)); fptest(3,Mod(1,3)*(x^27+x^5+x^3+x^2+2*x+2),Mod(1,3)*(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,Mod(1,2)*(x^40+x^5+x^4+x^3+1),Mod(1,2)*(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,Mod(1,2)*(x^16+x^15+x^14+x^12+x^7+x^6+x^5+x^2+1),Mod(1,2)*(x^16+x^5+x^3+x+1)); fptest(2,Mod(1,2)*(x^32+x^7+x^3+x^2+1),Mod(1,2)*(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,Mod(1,2)*(x^64+x^4+x^3+x+1),Mod(1,2)*(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,Mod(1,2)*(x^48+x^5+x^3+x^2+1),Mod(1,2)*(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,Mod(1,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 ),Mod(1,300007)*(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)); pari-2.5.5/src/test/in/polred0000644000175000017500000000210712147140047014470 0ustar billbillrnfpolredabs(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)) rnfpolredabs(nfinit(quadpoly(29,y)),quadray(29,17)) rnfpolredabs(nfinit(y^3-y-1),x^3-x-1) 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) pari-2.5.5/src/test/in/equal0000644000175000017500000000007312200712517014307 0ustar billbillO(3)===O(3) 1+O(3)===2+O(3) 1+O(3)==O(3^-1) 1+O(3)==2+O(3) pari-2.5.5/src/test/in/bezout0000644000175000017500000000237612147140047014523 0ustar billbill{ a=[0,0*x,O(5^3),2,2+O(5^3),x]; for(i=1,#a, for(j=1,#a, print(bezout(a[i],a[j])))); } bezout(-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))); bezout(AA,BB) pari-2.5.5/src/test/in/idealappr0000644000175000017500000000010411636712103015137 0ustar billbillidealaddtoone(nfinit(x),[1,[;]]); idealtwoelt(nfinit(x^2+23), 3, 6) pari-2.5.5/src/test/in/thue0000644000175000017500000000066012147140047014152 0ustar billbillallocatemem(20*10^6); do(p,a)=thue(thueinit(p), a); do(x^4 - 13*x^3 - 172*x^2 - 13*x + 1, 9) do(x^3 - 2, 2) do(x^6 - 2, 2638) do(x^3 + x^2 - 43690*x - 3529208, -3572896) do(x^4-x^3+x^2-x+1,1) do(x^3-48,320) do(x^7-401,88) thue(thueinit(x^3-100,1), 25) do((x+1)^2*(x^2+2), 12) do((4*x+1)^2*(x^2+2), 75) thueinit(x^0) do(23*x^4 + 40*x^3 - 600*x^2 + 160*x + 368, -144) do(x^3+92*x+1,3^3) do(x^3-18*x^2+81*x+1,3^3) do((x^4+1)^2,4) pari-2.5.5/src/test/in/bnr0000644000175000017500000000020412147140047013760 0ustar billbillsubgrouplist(bnrinit(bnfinit(x^3-x-1),10)); bnrL1(bnrinit(bnfinit(x^2+1),10,1),1); setrand(5);bnrL1(bnrinit(bnfinit(y^2+6),1,1),0); pari-2.5.5/src/test/in/modpr0000644000175000017500000000004011636712103014316 0ustar billbillnfeltmulmodpr(nfinit(x),x,x,1); pari-2.5.5/src/test/in/elliptic0000644000175000017500000000223712147140047015014 0ustar billbilldefault(realprecision,38); \e gettime; ellinit([0,0,0,-1,0]) ellinit([0,0,0,-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,%) ellpow(acurve,apoint,10) ellwp(acurve,,,32) q*Ser(ellan(acurve,100),q) \\ bcurve=ellinit([0,0,0,-3,0]) elllocalred(bcurve,2) elltaniyama(bcurve) \\ ccurve=ellinit([0,0,-1,-1,0]) l=elllseries(ccurve,2) elllseries(ccurve,2,1.2)-l \\ tcurve=ellinit([1,0,1,-19,26]); ellorder(tcurve,[1,2]) elltors(tcurve) \\ mcurve=ellinit([0,0,0,-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]) ellpow(cmcurve,[x,y],quadgen(-7)) \p 96 precision(cmcurve) getheap pari-2.5.5/src/test/in/bnfisintnorm0000644000175000017500000000047612147140047015722 0ustar billbilldo(i)=my(t = bnfisintnorm(bnf,i)); 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) pari-2.5.5/src/test/in/ff0000644000175000017500000000233212147140047013576 0ustar billbillallocatemem(50*10^6); { test(p,f) = setrand(1); a = ffgen(ffinit(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), if (2*a && 4*a^3+27, ellinit([0,0,0,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)) 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(ffinit(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(ffinit(7,4)); fflog(t^6,t^2) t = ffgen(ffinit(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) pari-2.5.5/src/test/in/subcyclo0000644000175000017500000000004511636712103015025 0ustar billbillpolsubcyclo(8,1) polsubcyclo(1048,2) pari-2.5.5/src/test/in/sumiter0000644000175000017500000000077111636712103014700 0ustar billbill\p 19 \e gettime; 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) getheap pari-2.5.5/src/test/in/padic0000644000175000017500000000052012147140047014260 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)) 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) pari-2.5.5/src/test/in/compat0000644000175000017500000003257112212100311014455 0ustar billbill\e default(compatible,3) gettime; +3 -5 5+3 5-3 5/3 5\3 5\/3 5%3 5^3 \precision=57 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) \\allocatemem(3000000) 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) \\draw([0,0,0]) 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) getheap() getrand() getstack() \\gettime()isattheend globalred(acurve) getstack() \\ 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);a=matrix(3,5,j,k,vvector(5,l,random()\10^8)) 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) setrand(1);as=matrix(3,3,j,k,vvector(5,l,random()\10^8)) nfsmith(nf,[as,[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<=j),2))); for(i=1,10, print(matfrobenius(matpascal(i),2))); for(i=1,8, print(matfrobenius(mathilbert(i),2))); } lindep([1,2,3], -3) 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) pari-2.5.5/src/test/in/cxtrigo0000644000175000017500000000143612147140047014666 0ustar billbillASIN(z) = -I*log(I*z + sqrt(1 - z^2)); ACOS(z) = -I*log(z + I*sqrt(1 - z^2)); ATAN(z) = (log(1+I*z) - log(1-I*z))/(2*I); ASINH(z) = log(z + sqrt(1 + z^2)); ACOSH(z) = 2*log(sqrt((z-1)/2) + sqrt((z+1)/2)); ATANH(z) = (log(1+z) - log(1-z))/2; fun = [asin,acos,atan,asinh,acosh,atanh]; FUN = [ASIN,ACOS,ATAN,ASINH,ACOSH,ATANH]; test(f, F, N = 8) = { my (h = 1./ N); forstep (re = -N, N, h, forstep (im = -N, N, h, trap(, printf ("%s: %.1f + I*%.1f is a pole ?\n", f, re, im) , my(mr, cr, dt); mr = f(re+im*I); cr = F(re+im*I); dt = mr - cr; if (abs(dt) > 1e-10, printf("%s(%.1f + I*%.1f):\t%.2g + I*%.2g\n", f, re, im, real(dt), imag(dt)); ) ) ) ); } for(k = 1, #fun, test(fun[k], FUN[k])); pari-2.5.5/src/test/in/ispower0000644000175000017500000000050412147140047014672 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 ]; } 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) pari-2.5.5/src/test/in/ellglobalred0000644000175000017500000000022612147140047015633 0ustar billbill{ 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)) ); } pari-2.5.5/src/test/in/addprimes0000644000175000017500000000100212147140047015144 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 = [moebius, 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]; 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(); pari-2.5.5/src/test/in/det0000644000175000017500000000203111636712103013753 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) 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.5.5/src/test/in/dirmul0000644000175000017500000000005412200714053014470 0ustar billbilldirmul([0,1],[0,1]) dirdiv([0,1,1,1,1],[1]) pari-2.5.5/src/test/in/diffop0000644000175000017500000000031412141040641014441 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]) pari-2.5.5/src/test/in/qfbsolve0000644000175000017500000000116211636712103015024 0ustar billbillgettime; qfbeval(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.5.5/src/test/in/combinat0000644000175000017500000000031612147140047014777 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)) vector(#v, i, permtonum(v[i])) stirling(100,0) pari-2.5.5/src/test/in/polchebyshev0000644000175000017500000000055112147140047015677 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, if (H(n+1)-2*x*H(n)+H(n)', print(n))) pari-2.5.5/src/test/in/nfrootsof10000644000175000017500000000053011636712103015301 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.5.5/src/test/in/polmod0000644000175000017500000000066112147140047014500 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 pari-2.5.5/src/test/in/quadray0000644000175000017500000000113511636712103014651 0ustar billbilldefault(realprecision,38); gettime; \\ 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) pari-2.5.5/src/test/in/partition0000644000175000017500000000102112147140047015206 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(2*10^4); numbpart(0) numbpart(52602) numbpart(147007) numbpart(10^15+2) partitions(1) partitions(9) partitions(9,3) partitions(-1) pari-2.5.5/src/test/in/intnum0000644000175000017500000000326111636712103014517 0ustar billbilldefault(echo,1); allocatemem(20 * 10^6); gettime; oo = [1]; \p96 intcirc(s=1, 0.5, zeta(s)) - 1 intlaplaceinv(x=2, 1, 1/x) - 1 m = intnumstep(); intlaplaceinv(x=2, 1, 1/x, m+1) - 1 intlaplaceinv(x=5, 1, 1/x) - 1 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); 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)); intnum(x = 0, [oo,1], f(x)) - Euler intnum(x = 0, [oo,1], g(x)) - Euler intnum(x = 0, 1, 1/sqrt(x)) - 2 intnum(x = [0,-1/2], 1, 1/sqrt(x)) - 2 intnum(x = 0, [oo,1], sin(x)/x) - Pi/2 intnum(x = 0, [oo,-I], sin(x)/x) - Pi/2 intnum(x = 0, [oo,-2*I], sin(2*x)/x) - Pi/2 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 intnum(x = 0, [oo, 1], sin(x)^3*exp(-x)) - 0.3 intnum(x = 0, [oo,-I], sin(x)^3*exp(-x)) - 0.3 tab = intnuminit(0,[oo,-I], m+1); intnum(x = 0, oo, sin(x)^3*exp(-x), tab) - 0.3 intnum(x = 0, [oo, -I], x^2*sin(x)) + 2 tab = intnuminit(-1,1); 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); a - b 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)); d - c sumnum(n=1,2,n^(-4/3),,1) - zeta(4/3) tab = sumnuminit([2,-3/2]); sumnum(n=1,[2,-3/2],1/(n*sqrt(n)),tab,1)-zeta(3/2) \\ suminf(n=1, 2^(-n)) - 1 sumpos(n=1, 2^(-n)) - 1 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)); a - b pari-2.5.5/src/test/in/charpoly0000644000175000017500000000026111636712103015023 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]) minpoly(matrix(4,4,i,j,i/j)) pari-2.5.5/src/test/in/extract0000644000175000017500000000056012147140047014656 0ustar billbillA=vector(100,i,i); for(i=35,99, print1(vecextract(A,1<1/x)(0) print(); pari-2.5.5/src/test/in/number0000644000175000017500000000371212147140047014476 0ustar billbilldefault(realprecision,38); \e gettime; addprimes([nextprime(10^9),nextprime(10^10)]) bestappr(Pi,10000) bezout(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) getheap pari-2.5.5/src/test/in/ideal0000644000175000017500000000032312147140047014257 0ustar billbillQi = nfinit(x^2+1); idealintersect(Qi,0,1) Q = nfinit(y); idealaddtoone(Q,[1,[;]]) idealaddtoone(Q,[1,[;],Mat(1/2)]) ideallog(Q,2,idealstar(Q,4,1)) idealstar(Qi,matdiagonal([6,12])) idealintersect(Qi, 1/2,1/2) pari-2.5.5/src/test/in/krasner0000644000175000017500000000114012147140047014644 0ustar billbillallocatemem(20*10^6); cmp(x, y) = sign(x[1] - y[1])*8 + sign(x[2] - y[2])*4 + sign(x[3] - y[3])*2 + sign(x[4] - y[4]); filter_output(p, v) = vecsort(vector(#v, j, [valuation(poldisc(v[j][1]), p), v[j][2], v[j][3], v[j][4]]), cmp); p = 2; for (d = 2, 50, if (d%p, print(filter_output(p, padicfields(p, d, 1))))) p = 3; for (d = 2, 50, if (d%p, print(filter_output(p, padicfields(p, d, 1))))) filter_output(2, padicfields(2, 105, 1)) filter_output(5, padicfields(5, 21, 1)) filter_output(23, padicfields(23, 55, 1)) filter_output(23459, padicfields(23459, 12, 1)) filter_output(2, padicfields(2, [8, 12], 1)) pari-2.5.5/src/test/in/objets0000644000175000017500000000156411636712103014477 0ustar billbilldefault(realprecision,38); \e gettime; +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 getheap pari-2.5.5/src/test/in/random0000644000175000017500000000046411636712103014467 0ustar billbillff(p,f) = ffgen(ffinit(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)) pari-2.5.5/src/test/in/ploth0000644000175000017500000000177512147140047014343 0ustar billbill\e \p19 gettime; 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]) pari-2.5.5/src/test/in/galoisinit0000644000175000017500000000576712141173372015365 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) 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) 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); pari-2.5.5/src/test/in/aurifeuille0000644000175000017500000000057011636712103015513 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.5.5/src/test/in/factorint0000644000175000017500000000011112141040641015156 0ustar billbillfactorint(-33623546348886051018593728804851,1) factorint(691160558642,1) pari-2.5.5/src/test/in/round0000644000175000017500000000007412212110474014325 0ustar billbilldefault(realprecision,38); round((1e-40 + x) / (1e-39 + x)) pari-2.5.5/src/test/in/qf0000644000175000017500000000006112147140047013606 0ustar billbillqfgaussred([0,7,2,3; 7,0,6,8; 2,6,0,9; 3,8,9,0]) pari-2.5.5/src/test/in/debugger0000644000175000017500000000044312147140047014770 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] break pari-2.5.5/src/test/in/rnf0000644000175000017500000000221212147140047013765 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) \\#1157 rnfisnorminit(y,x^2-Mod(2+y,y)); \\#1256 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) pari-2.5.5/src/test/in/zn0000644000175000017500000000006312147140047013631 0ustar billbillznprimroot(9223372036854775837) Mod(10,148)^(2^64) pari-2.5.5/src/test/in/printf0000644000175000017500000000406512141040641014503 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) pari-2.5.5/src/test/in/exact00000644000175000017500000000112411636712103014365 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.5.5/src/test/in/subfields0000644000175000017500000000622411636712103015167 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]))) pari-2.5.5/src/test/in/nf0000644000175000017500000000203612147140047013607 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!)); zetakinit(2*x-1); nf=nfinit(y^5-4*y^3+2*y+11); v = [4/3, -1, y^2+y+1, [1,2,3,4,5]~]; for (i=1, #v, print( nfelttrace(nf,v[i]) )) for (i=1, #v, print( nfeltnorm(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) pari-2.5.5/src/test/in/ellweilpairing0000644000175000017500000000410312167755161016223 0ustar billbillweil(v,P,Q,m,p)=lift(ellweilpairing(ellinit(v*Mod(1,p)),P*Mod(1,p),Q*Mod(1,p),m)); tate(v,P,Q,m,p)=if(p%m!=1,return(0));lift(elltatepairing(ellinit(v*Mod(1,p)),P*Mod(1,p),Q*Mod(1,p),m)^((p-1)/m)); cyc(E,p)=ellgroup(ellinit(E),p); check(v,P,Q,m,p)=print([weil(v,P,Q,m,p),tate(v,P,Q,m,p),cyc(v,p)]); 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); { forvec(v=vector(5,i,[0,2]),E=trap(talker,0,ellinit(v*Mod(1,3))); if(E,G=ellgroup(E,3);if(#G>1,print(v,":",G)))) } { forvec(v=vector(5,i,[0,4]),E=trap(talker,0,ellinit(v*Mod(1,5))); if(E,G=ellgroup(E,5);if(#G>1,print(v,":",G)))) } pari-2.5.5/src/test/in/program0000644000175000017500000000205711636712103014656 0ustar billbilldefault(realprecision,38); \e gettime; 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,Pi,Pi/12,print(sin(x))) forvec(x=[[1,3],[-2,2]],print1([x[1],x[2]]," "));print(" "); getheap getrand getstack 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) setrand(10) 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(realprecision,28) 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)) ) ); } /* added in 1.924.13 */ install(addii,GG) addii(1,2) kill(addii) /* up to here */ getheap pari-2.5.5/src/test/in/intformal0000644000175000017500000000002111636712103015167 0ustar billbillintformal(1-A,Y) pari-2.5.5/src/test/in/resultant0000644000175000017500000000265212147140047015231 0ustar billbillgettime(); allocatemem(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 bezoutres(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) pari-2.5.5/src/test/in/minim0000644000175000017500000000230311706644717014327 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.5.5/src/test/in/linear0000644000175000017500000000530312147140047014456 0ustar billbilldefault(realprecision,38); \e gettime; 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],-2) 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,3) 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)) aset=Set([5,-2,7,3,5,1]) bset=Set([7,5,-5,7,2]) setintersect(aset,bset) setisset([-3,5,7,7]) setminus(aset,bset) setsearch(aset,3) setsearch(bset,3) setunion(aset,bset) 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]],,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) getheap pari-2.5.5/src/test/64/0000755000175000017500000000000012212611624013100 5ustar billbillpari-2.5.5/src/test/64/nfields0000644000175000017500000014664412147140047014471 0ustar billbill echo = 1 (on) ? gettime;p2=Pol([1,3021,-786303,-6826636057,-546603588746,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] ? setrand(1);a=matrix(3,5,j,k,vectorv(5,l,random\10^8)); ? setrand(1);as=matrix(3,3,j,k,vectorv(5,l,random\10^8)); ? 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.072312766896812300380582649294307897075 + 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]]], [-2.428 5174907194186068992069565359418365, 1.9647119211288133163138753392090569931 + 0.80971492418897895128294082219556466857*I, -0.750453175769104012864271860 94108607489 + 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 837196 - 1.5701452385894131769052374806001981109*I; 1, 1.6829412935943127761 629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.750453175 76910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, - 0.78742068874775359433940488309213323160 + 2.1336633893126618034168454610457 936016*I, 1.2658732110596551455718089553258673705 - 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]]], [-1.0891151457205048250249527946671612684, -0.13838372073406036365047 976417441696637 + 0.49181637657768643499753285514741525107*I, 1.682941293594 3127761629561615079976006 + 2.0500351226010726172974286983598602164*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) [[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 2837196 - 1.5701452385894131769052374806001981109*I; 1, 1.682941293594312776 1629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.75045317 576910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, -0.78742068874775359433940488309213323160 + 2.133663389312661803416845461045 7936016*I, 1.2658732110596551455718089553258673705 - 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]]], [-1.0891151457205048250249527946671612684, -0.1383837207340603636504 7976417441696637 + 0.49181637657768643499753285514741525107*I, 1.68294129359 43127761629561615079976006 + 2.0500351226010726172974286983598602164*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)] ? nf3=nfinit(x^6+108); ? nf4=nfinit(x^3-10*x+8) [x^3 - 10*x + 8, [3, 0], 568, 2, [[1, -0.36332823793268357037416860931988791 957, -3.1413361156553641347759399165844441384; 1, -1.76155718183189058754537 11274124874988, 2.6261980685272936133764995500786243868; 1, 3.12488541976457 41579195397367323754184, -0.48486195287192947860055963349418024847], [1, -0. 36332823793268357037416860931988791957, -3.141336115655364134775939916584444 1384; 1, -1.7615571818318905875453711274124874988, 2.62619806852729361337649 95500786243868; 1, 3.1248854197645741579195397367323754184, -0.4848619528719 2947860055963349418024847], [1, 0, -3; 1, -2, 3; 1, 3, 0], [3, 1, -1; 1, 13, -5; -1, -5, 17], [284, 76, 46; 0, 2, 0; 0, 0, 1], [98, -6, 4; -6, 25, 7; 4, 7, 19], [284, [60, 418, -204; 105, 270, -2; 1, 104, -46]]], [-3.50466435358 80477051501085259043320579, 0.86464088669540302583112842266613688801, 2.6400 234668926446793189801032381951699], [1, 1/2*x^2 + x - 3, -1/2*x^2 + 3], [1, 0, 6; 0, 1, 0; 0, 1, -2], [1, 0, 0, 0, 4, -2, 0, -2, 6; 0, 1, 0, 1, 2, 0, 0, 0, -2; 0, 0, 1, 0, 1, -1, 1, -1, -1]] ? 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, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.71246530518434397468087951060 61300701 - 3.1415926535897932384626433832795028843*I; 2.71246530518434397468 08795106061300701 - 6.2831853071795864769252867665590057684*I], [-0.92212354 848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.70148550268542821846861610071436 900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.50057980363245 587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.623 6090511720428168202836906902792025, -0.5788359042095875039617797232424909750 4, -0.34328764427702709438988786673341921877 + 3.141592653589793238462643383 2795028842*I, 0.066178301882745732185368492323164193427 + 3.1415926535897932 384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.922123 54848661459835166758997591019383, 1.4227033521190704721778709033666269682, - 0.70148550268542821846861610071436900869 + 3.1415926535897932384626433832795 028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.6236090511720 428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.5788 3590420958750396177972324249097504, 0.34328764427702709438988786673341921877 , -0.066178301882745732185368492323164193427, 0.9883018503693603305370360822 9907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57 ; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, - 2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0] ]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.066372975210777963595931024670 5326059; 1, 8.0663729752107779635959310246705326059], [1, -7.066372975210777 9635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.06637297521077796359 59310246705326059], [1, x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [ 3], [[3, 2; 0, 1]]], 2.7124653051843439746808795106061300701, 1, [2, -1], [x + 7]], [Mat(1), [[0, 0]], [[-0.92212354848661459835166758997591019383 + 3.1 415926535897932384626433832795028842*I, 0.9221235484866145983516675899759101 9383]]], 0] ? setrand(1);bnfinit(x^2-x-100000,1) [Mat(5), Mat([3, 2, 1, 2, 0, 3, 2, 3, 3, 2, 0, 0, 4, 1, 3, 2, 2, 3]), [-129. 82045011403975460991182396195022419 - 3.624180943686747091 E-113*I; 129.8204 5011403975460991182396195022419 + 1.2486673839592994179 E-113*I], [-41.81126 4589129943393339502258694361489 + 6.2831853071795864769252867665590057684*I, 9.2399004147902289816376260438840931575, -11.874609881075406725097315997431 161032 + 3.1415926535897932384626433832795028842*I, 0, 598.05108556627860067 458199150717266631 + 2.079081953128979844 E-112*I, -194.73067517105963191486 773594292533629 + 3.1415926535897932384626433832795028842*I, -289.5775549361 3404588806583418516364884 + 3.1415926535897932384626433832795028842*I, 102.9 8937362955842429020308089254908188 + 3.898278662116837207 E-113*I, -404.4415 3844676787690336623107514389175 + 3.1415926535897932384626433832795028842*I, 484.20828704532476310708802954016117339 + 3.1415926535897932384626433832795 028842*I, 123.08269893574406654913158801089558608 + 3.898278662116837207 E-1 13*I, -731.25438161267029366213802528899365727 + 6.2831853071795864769252867 665590057684*I, 601.43393149863053905222620132704343308 + 2.0790819531289798 44 E-112*I, 1093.4420050106303665241166125712749392 + 3.14159265358979323846 26433832795028842*I, -745.79191925764104608772064294411862807 + 3.1415926535 897932384626433832795028842*I, -671.20676609281265093040971423356733550 + 6. 2831853071795864769252867665590057684*I, 239.9341511615634437073347400890223 0144 + 3.1415926535897932384626433832795028842*I, 652.9785442166766555563076 0228878662857 + 3.1415926535897932384626433832795028842*I, -1733.35340971812 46358289416962430827836 + 6.2831853071795864769252867665590057684*I; 41.8112 64589129943393339502258694361489 + 8.933555267351085266 E-114*I, -9.23990041 47902289816376260438840931575 + 3.1415926535897932384626433832795028842*I, 1 1.874609881075406725097315997431161032 + 2.030353469852519379 E-115*I, 0, -5 98.05108556627860067458199150717266631 + 3.141592653589793238462643383279502 8842*I, 194.73067517105963191486773594292533629 + 3.248565551764031006 E-113 *I, 289.57755493613404588806583418516364884 + 4.547991772469643408 E-113*I, -102.98937362955842429020308089254908188 + 3.1415926535897932384626433832795 028842*I, 404.44153844676787690336623107514389175 + 6.497131103528062012 E-1 13*I, -484.20828704532476310708802954016117339 + 6.2831853071795864769252867 665590057684*I, -123.08269893574406654913158801089558608 + 3.141592653589793 2384626433832795028842*I, 731.25438161267029366213802528899365727 + 1.299426 2207056124024 E-112*I, -601.43393149863053905222620132704343308 + 6.28318530 71795864769252867665590057684*I, -1093.4420050106303665241166125712749392 + 3.1415926535897932384626433832795028842*I, 745.79191925764104608772064294411 862807 + 3.1415926535897932384626433832795028842*I, 671.20676609281265093040 971423356733550 + 3.1415926535897932384626433832795028842*I, -239.9341511615 6344370733474008902230144 + 6.2831853071795864769252867665590057684*I, -652. 97854421667665555630760228878662857 + 3.141592653589793238462643383279502884 2*I, 1733.3534097181246358289416962430827836 + 2.598852441411224805 E-112*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, 1000 00; 1, 4]], [13, [5, 1]~, 1, 1, [-6, 100000; 1, -5]], [31, [23, 1]~, 1, 1, [ 7, 100000; 1, 8]], [31, [38, 1]~, 1, 1, [-8, 100000; 1, -7]], [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]], [29, [-14, 1]~, 1, 1, [13, 100000; 1, 14]], [29, [13, 1]~, 1, 1, [-14, 1000 00; 1, -13]], [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.7281613012984016139208 9489603747004], [1, -315.72816130129840161392089489603747004; 1, 316.7281613 0129840161392089489603747004], [1, -316; 1, 317], [2, 1; 1, 200001], [400001 , 200000; 0, 1], [200001, -1; -1, 2], [400001, [200000, 100000; 1, 200001]]] , [-315.72816130129840161392089489603747004, 316.728161301298401613920894896 03747004], [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], [379554 884019013781006303254896369154068336082609238336*x + 11983616564425078999046 2835950022871665178127611316131167]], [Mat(1), [[0, 0]], [[-41.8112645891299 43393339502258694361489 + 6.2831853071795864769252867665590057684*I, 41.8112 64589129943393339502258694361489 + 8.933555267351085266 E-114*I]]], 0] ? \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, 1, 1]), [9, 15, 16, 33, 39, 17, 10, 57, 69], [2, -1], [[0, 1, 0]~, [ 5, 3, 1]~], [[[4, -1, 0]~, [1, -1, 0]~, [-2, -1, 0]~, [1, 1, 0]~, [10, 5, 1] ~, [3, 1, 0]~, [3, 0, 0]~, [7, 2, 0]~, [-2, -1, 1]~], 0]] ? \p38 realprecision = 38 significant digits ? bnr=bnrinit(bnf,[[5,3;0,1],[1,0]],1) [[Mat(3), Mat([1, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.7124653051843439746808795106 061300701 - 3.1415926535897932384626433832795028843*I; 2.7124653051843439746 808795106061300701 - 6.2831853071795864769252867665590057684*I], [-0.9221235 4848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.7014855026854282184686161007143 6900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.5005798036324 5587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.62 36090511720428168202836906902792025, -0.578835904209587503961779723242490975 04, -0.34328764427702709438988786673341921877 + 3.14159265358979323846264338 32795028842*I, 0.066178301882745732185368492323164193427 + 3.141592653589793 2384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.92212 354848661459835166758997591019383, 1.4227033521190704721778709033666269682, -0.70148550268542821846861610071436900869 + 3.141592653589793238462643383279 5028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.623609051172 0428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.578 83590420958750396177972324249097504, 0.3432876442770270943898878667334192187 7, -0.066178301882745732185368492323164193427, 0.988301850369360330537036082 29907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 5 7; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, -2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0 ]]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.06637297521077796359593102467 05326059; 1, 8.0663729752107779635959310246705326059], [1, -7.06637297521077 79635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7 ; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.0663729752107779635 959310246705326059], [1, x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2.7124653051843439746808795106061300701, 1, [2, -1], [ x + 7]], [Mat(1), [[0, 0]], [[-0.92212354848661459835166758997591019383 + 3. 1415926535897932384626433832795028842*I, 0.922123548486614598351667589975910 19383]]], [0, [Mat([[5, 1]~, 1])]]], [[[5, 3; 0, 1], [1, 0]], [8, [4, 2], [2 , [-4, 0]~]], Mat([[5, [-2, 1]~, 1, 1, [1, 1]~], 1]), [[[[4], [[2, 0]~], [[2 , 0]~], [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]] ? rnfinit(nf2,x^5-x-2) [x^5 - x - 2, [], [[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.75487766624669276004950889635852869190, 1.324717957244746025960908 8544780973407; 1, -0.87743883312334638002475444817926434595 - 0.744861766619 74423659317042860439236724*I, -0.66235897862237301298045442723904867037 + 0. 56227951206230124389918214490937306150*I], [1, 0.754877666246692760049508896 35852869190, 1.3247179572447460259609088544780973407; 1, -1.6223005997430906 166179248767836567132, -0.10007946656007176908127228232967560887; 1, -0.1325 7706650360214343158401957487197871, -1.2246384906846742568796365721484217319 ], [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]]], [1.3247179572447460259609088544780973407, -0.662358978622373 01298045442723904867037 + 0.56227951206230124389918214490937306150*I], [1, y ^2 - 1, y], [1, 0, 1; 0, 0, 1; 0, 1, 0], [1, 0, 0, 0, 0, 1, 0, 1, 1; 0, 1, 0 , 1, -1, 0, 0, 0, 1; 0, 0, 1, 0, 1, 0, 1, 0, 0]], [x^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 + 1 89*x^3 + 144*x^2 + 25*x + 1, Mod(39516536165538345/83718587879473471*x^14 - 6500512476832995/83718587879473471*x^13 - 196215472046117185/837185878794734 71*x^12 + 229902227480108910/83718587879473471*x^11 + 237380704030959181/837 18587879473471*x^10 - 1064931988160773805/83718587879473471*x^9 - 2065708667 1714300/83718587879473471*x^8 + 1772885205999206010/83718587879473471*x^7 + 5952033217241102348/83718587879473471*x^6 - 4838840187320655696/837185878794 73471*x^5 + 5180390720553188700/83718587879473471*x^4 - 8374015687535120430/ 83718587879473471*x^3 + 8907744727915040221/83718587879473471*x^2 + 41559766 64123434381/83718587879473471*x + 318920215718580450/83718587879473471, 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), -1], 0] ? bnfcertify(bnf) 1 ? setrand(1);bnfinit(x^2-x-100000,1).fu [Mod(379554884019013781006303254896369154068336082609238336*x + 119836165644 250789990462835950022871665178127611316131167, x^2 - x - 100000)] ? setrand(1);bnfinit(x^4+24*x^2+585*x+1791,,[0.1,0.1]) [Mat(4), Mat([1, 3, 2, 2, 1, 2, 2, 3, 1, 3, 1]), [3.794126968821658934140827 4220859400302 + 17.051293362170144593106294159002845606*I; -3.79412696882165 89341408274220859400302 + 12.270238071334592299211710751605847980*I], [1.931 3880959585148864147377738135342090 + 2.6094045420344387591770907735373697726 *I, -4.701977403289150032 E-38 + 11.899424269855508723178392022414809397*I, -3.9880090562278299060379033618568304190 + 4.8170180346492352747549401763817 845238*I, 0.96569404797925744320736888690676710450 + 1.828301046615518252665 6526173152687003*I, -0.93136943643157202386304482413620291064 + 10.990051815 371901190031232280542867475*I, 2.1252701833646858583118137135844245978 + 0.2 5759541125748255276389824853295908861*I, 3.117999308786939916447700453089569 1176 + 11.763189456789071757159536232166443442*I, 2.607515755993233904107864 7428099051217 + 3.2235904944381500597928062956324708834*I, 0.807090594795827 43770186957565773006252 + 8.6810952775533156350341070283687472525*I, 1.12429 75011626874487128681981558041465 + 0.69662231985168015178245507209625882934* I, 2.1166141872052248127966075549404537821 + 10.0938249624782783222208828410 41949946*I, -0.18522609124670992638186978112691957309 + 0.075884278933757561 441547351857249422597*I; -1.9313880959585148864147377738135342090 + 7.289180 6943100772719847567167678332032*I, 4.701977403289150032 E-38 + 11.8994242698 55508723178392022414809397*I, 3.9880090562278299060379033618568304190 + 2.22 66696859162182331344124909571522200*I, -0.9656940479792574432073688869067671 0449 + 10.451374429932923985994772355489506184*I, 0.931369436431572023863044 82413620291066 + 9.4372822297479101164570701892975922345*I, -2.1252701833646 858583118137135844245978 + 12.308775203101690401086675284585052448*I, -3.117 9993087869399164477004530895691175 + 9.4561362323377796461746343301082095543 *I, -2.6075157559932339041078647428099051217 + 5.429364580329528389690790733 5241705757*I, -0.80709059479582743770186957565773006250 + 8.6527493586654216 544393932995672941726*I, -1.1242975011626874487128681981558041465 + 5.404744 3910152126451848347441281753397*I, -2.1166141872052248127966075549404537821 + 8.0320113177474990640984855793282847659*I, 0.18522609124670992638186978112 691957310 + 6.8174740759401753323716105568013780333*I], [[7, [-2, 3, 3, -1]~ , 1, 1, [3, 1, 56, 11; 4, 6, -7, 45; 4, -1, 7, -4; 1, 5, 0, 6]], [7, [1, -6, -2, 1]~, 1, 1, [3, 1, -12, -35; 0, 0, 35, 21; -2, -3, 1, 0; 3, 1, 2, 0]], [ 7, [2, -6, -2, 1]~, 1, 1, [2, -1, -1, 30; -1, 4, -31, -29; 1, 3, 3, 1; -3, - 2, -2, 4]], [3, [-1, 0, 1, 0]~, 4, 1, [0, 0, 18, -3; 2, 1, 5, 20; 1, -1, 1, -2; 1, 2, 1, 1]], [19, [-5, -6, -2, 1]~, 2, 1, [9, 13, 36, -14; -8, -1, 6, 6 1; 3, -2, 12, 8; 2, 5, -11, -1]], [7, [7, -2, -1, 3]~, 1, 1, [2, -1, 32, 3; 4, 5, 1, 27; 2, -1, 4, -4; 1, 3, 2, 5]], [13, [-1, -6, -2, 1]~, 1, 1, [-3, 9 , 19, -28; -5, -11, 23, 53; 1, -3, -2, 5; 3, 4, -6, -11]], [13, [0, -6, -2, 1]~, 1, 1, [4, 14, 89, -24; -3, -4, 21, 122; 6, -5, 10, 3; 5, 11, -9, -4]], [13, [8, -6, -2, 1]~, 1, 1, [6, 11, 77, 3; -3, 1, -6, 83; 6, -2, 12, 3; 2, 8 , -9, 1]], [13, [9, -6, -2, 1]~, 1, 1, [-6, 2, -9, 35; -5, -7, -40, -38; 1, 4, -5, 5; -4, -3, -6, -7]], [19, [-4, -6, -2, 1]~, 1, 1, [8, 7, 20, -76; 0, 0, 76, 95; -1, -8, 7, 0; 8, 7, 1, 0]], [19, [11, -6, -2, 1]~, 1, 1, [9, -4, -133, -9; -9, 4, 0, -124; -9, 4, 0, 9; -4, -13, 0, 4]]], 0, [x^4 + 24*x^2 + 585*x + 1791, [0, 2], 18981, 3087, [[1, 0.4999999999999999999999999999999999 9995 - 0.86602540378443864676372317075293618353*I, -3.0933488079472828155742 243261531931904 - 0.11742462569605115853137757107804136513*I, -2.64836711285 63006823406123980207685802 + 2.6202063376006319767212962440086284031*I; 1, 0 .50000000000000000000000000000000000000 - 0.86602540378443864676372317075293 618347*I, 3.5933488079472828155742243261531931904 + 0.9834500294804898052951 0074183097754868*I, 1.6483671128563006823406123980207685802 - 2.620206337600 6319767212962440086284032*I], [1, -0.36602540378443864676372317075293618358, -3.2107734336433339741056018972312345555, -0.028160775255668705619316154012 140177111; 1, 1.3660254037844386467637231707529361835, -2.975924182251231657 0428467550751518252, -5.2685734504569326590619086420293969833; 1, -0.3660254 0378443864676372317075293618347, 4.5767988374277726208693250679841707391, -0 .97183922474433129438068384598785982299; 1, 1.366025403784438646763723170752 9361835, 2.6098987784667930102791235843222156418, 4.268573450456932659061908 6420293969834], [1, 0, -3, 0; 1, 1, -3, -5; 1, 0, 5, -1; 1, 1, 3, 4], [4, 2, 1, -2; 2, -2, 2, -1; 1, 2, 43, 34; -2, -1, 34, -8], [2109, 363, 1926, 1236; 0, 3, 0, 2; 0, 0, 3, 1; 0, 0, 0, 1], [317, 360, 17, -52; 360, -700, 6, 23; 17, 6, 12, 46; -52, 23, 46, -58], [2109, [-993, -60, 7618, 2957; 642, -352, -2315, 4600; 581, -1, -412, -642; 1, 582, 61, -352]]], [4.538330503038264948 8078362542856178008 + 8.0512080116993661743663904106823282345*I, -4.53833050 30382649488078362542856178008 + 0.60904602614502029327084129684703360027*I], [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], [1, 4, 15, -480; 0, -6, -39, 42; 0, -2, 0, 99; 0, 1, 15, 9], [1, 0, 0, 0, 0, -1, 1, 1, 0, 1, 12, 4, 0, 1, 4, -9; 0, 1, 0, 0, 1, 1, 0, -1, 0, 0, -4 , 9, 0, -1, 9, 13; 0, 0, 1, 0, 0, 0, 0, -1, 1, 0, 1, 0, 0, -1, 0, 0; 0, 0, 0 , 1, 0, 0, 1, 1, 0, 1, -1, 0, 1, 1, 0, -1]], [[4, [4], [[7, 2, 4, 0; 0, 1, 0 , 0; 0, 0, 1, 0; 0, 0, 0, 1]]], 3.7941269688216589341408274220859400302, 1, [6, 10/1029*x^3 - 13/343*x^2 + 165/343*x + 1478/343], [4/1029*x^3 + 53/1029* x^2 + 66/343*x + 111/343]], [Mat(-1), [[1.9459101490553133051053527434431797 297 + 3.5218438602827267539446763336694683720*I, 1.9459101490553133051053527 434431797296 + 3.5218438602827267539446763336694683721*I]], [[5.852252500262 7383340066731999591847100 + 11.477970899096468256601614561140503715*I, 9.715 0286921797681068361487475862531275 + 6.7981947468208297437939486179100402854 *I]]], 0] ? 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)]~ ? \p19 realprecision = 19 significant digits ? bnfinit(sbnf) [Mat(2), Mat([1, 1, 0, 1, 0, 1, 1, 1]), [1.173637103435061715 + 3.1415926535 89793239*I, -4.562279014988837911 + 3.141592653589793239*I; -2.6335434327389 76050 + 3.141592653589793239*I, 1.420330600779487358 + 3.141592653589793239* I; 1.459906329303914335, 3.141948414209350544], [1.246346989334819161, 0.540 4006376129469728, -0.6926391142471042845, 0.004375616572659815434 + 3.141592 653589793239*I, -0.8305625946607188642 + 3.141592653589793239*I, -1.99005644 5584799713 + 3.141592653589793239*I, 0, -1.977791147836553954, 0.36772620140 27817707; 0.6716827432867392935, -0.8333219883742404172, -0.2461086674077943 078 + 3.141592653589793239*I, -0.8738318043071131266, -1.552661549868775854, 0.5379005671092853266, 0, 0.5774919091398324094, 0.9729063188316092381 + 3. 141592653589793239*I; -1.918029732621558454 + 3.141592653589793239*I, 0.2929 213507612934446 + 3.141592653589793239*I, 0.9387477816548985924 + 3.14159265 3589793239*I, 0.8694561877344533112, 2.383224144529494719, 1.452155878475514 387, 0, 1.400299238696721545, -1.340632520234391008 + 3.141592653589793239*I ], [[3, [-1, 1, 0]~, 1, 1, [1, 1, 1]~], [5, [-1, 1, 0]~, 1, 1, [0, 1, 1]~], [5, [2, 1, 0]~, 1, 1, [1, -2, 1]~], [11, [1, 1, 0]~, 1, 1, [-3, -1, 1]~], [1 3, [19, 1, 0]~, 1, 1, [-2, -6, 1]~], [5, [3, 1, 0]~, 1, 1, [2, 2, 1]~], [3, [10, 1, 1]~, 1, 2, [-1, 1, 0]~], [19, [-6, 1, 0]~, 1, 1, [6, 6, 1]~], [23, [ -10, 1, 0]~, 1, 1, [-7, 10, 1]~]]~, 0, [x^3 - x^2 - 14*x - 1, [3, 0], 10889, 1, [[1, -3.233732695981516673, 4.690759845041404812; 1, -0.0718235090274363 6345, -8.923017874523549404; 1, 4.305556205008953037, 5.232258029482144592], [1, -3.233732695981516673, 4.690759845041404812; 1, -0.07182350902743636345 , -8.923017874523549404; 1, 4.305556205008953037, 5.232258029482144592], [1, -3, 5; 1, 0, -9; 1, 4, 5], [3, 1, 1; 1, 29, 8; 1, 8, 129], [10889, 5698, 89 94; 0, 1, 0; 0, 0, 1], [3677, -121, -21; -121, 386, -23; -21, -23, 86], [108 89, [1899, 46720, 5235; 5191, 7095, 25956; 1, 5191, 1895]]], [-3.23373269598 1516673, -0.07182350902743636345, 4.305556205008953037], [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.34800724602768001, 1, [2, -1], [x, x^2 + 2*x - 4]], [Mat(1), [[0, 0, 0]], [[1.246346989334819161, 0.6716827432867392935, -1.918029732621558454 + 3.141592653589793239*I]]], [[[4, -1, 0]~, [1, -1, 0]~, [-2, -1, 0]~, [1, 1, 0]~, [10, 5, 1]~, [3, 1, 0]~, [3, 0, 0]~, [7, 2, 0]~, [-2, -1, 1]~], 0]] ? \p38 realprecision = 38 significant digits ? bnfnarrow(bnf) [3, [3], [[3, 2; 0, 1]]] ? bnfsignunit(bnf) [-1] [1] ? bnr2=bnrinit(bnf,[[25,13;0,1],[1,1]],1) [[Mat(3), Mat([1, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.7124653051843439746808795106 061300701 - 3.1415926535897932384626433832795028843*I; 2.7124653051843439746 808795106061300701 - 6.2831853071795864769252867665590057684*I], [-0.9221235 4848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.7014855026854282184686161007143 6900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.5005798036324 5587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.62 36090511720428168202836906902792025, -0.578835904209587503961779723242490975 04, -0.34328764427702709438988786673341921877 + 3.14159265358979323846264338 32795028842*I, 0.066178301882745732185368492323164193427 + 3.141592653589793 2384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.92212 354848661459835166758997591019383, 1.4227033521190704721778709033666269682, -0.70148550268542821846861610071436900869 + 3.141592653589793238462643383279 5028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.623609051172 0428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.578 83590420958750396177972324249097504, 0.3432876442770270943898878667334192187 7, -0.066178301882745732185368492323164193427, 0.988301850369360330537036082 29907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 5 7; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, -2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0 ]]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.06637297521077796359593102467 05326059; 1, 8.0663729752107779635959310246705326059], [1, -7.06637297521077 79635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7 ; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.0663729752107779635 959310246705326059], [1, x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2.7124653051843439746808795106061300701, 1, [2, -1], [ x + 7]], [Mat(1), [[0, 0]], [[-0.92212354848661459835166758997591019383 + 3. 1415926535897932384626433832795028842*I, 0.922123548486614598351667589975910 19383]]], [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, 1]~], 2]), [[[[4 ], [[2, 0]~], [[2, 0]~], [Vecsmall([0, 0])], 1], [[5], [[6, 0]~], [[6, 0]~], [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]], [1], Mat([1, -3, -6, -6]), [12, [12], [[3, 2; 0, 1]]], [[0, 2, 0; -1, 10, 0], [- 2, 0; 0, -10], 2]] ? 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(nf4,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, -1, -1, -1, 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] [[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, [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]] ? 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, -1, -1, -1, 0]~] 1] [[5, [-1, 0, 0, 0, 2]~, 4, 1, [2, 2, 1, 2, 1]~] 3] [[5, [2, 0, 0, 0, -2]~, 1, 1, [2, 0, 3, 0, 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], [[1, 1, 0]~], [[1, - 27, 0]~], [Vecsmall([])], 1]], [[[26], [[4, 2, 1]~], [[-23, 2, -26]~], [Vecs mall([])], 1], [[3, 3, 3], [[4, 0, 0]~, [1, 3, 0]~, [1, 0, 3]~], [[-23, 0, 0 ]~, [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, 0, 0]~, [1, 9, 0]~, [ 1, 0, 9]~], [[-17, 0, 0]~, [1, -18, 0]~, [1, 0, -18]~], [Vecsmall([]), Vecsm all([]), Vecsmall([])], [1/9, 0, 0; 0, 1/9, 0; 0, 0, 1/9]]], [[], [], []]], [468, -77, 0, 728, -1456, 0, 546, -1092; 0, 0, 1, 0, -1, -6, 0, -3; 0, 1, 0, -1, 1, 0, -3, 3]] ? ideallog(nf2,y,bid) [752, 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, 0, 0, 1, 1]~], [2, [12, -4, -2, 11, 3]~, 1, 4, [1, 0, 1, 0, 0]~]] ? idealprimedec(nf,3) [[3, [1, 0, 1, 0, 0]~, 1, 1, [1, -1, -1, -1, 0]~], [3, [1, 1, 1, 0, 0]~, 2, 2, [0, 2, 2, 1, 0]~]] ? 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], [[2, 1, 0]~], [[-25, -26, 0]~], [ Vecsmall([])], 1], [[3, 3, 3], [[4, 0, 0]~, [1, 3, 0]~, [1, 0, 3]~], [[-23, 0, 0]~, [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, 0, 0]~, [1, 9, 0] ~, [1, 0, 9]~], [[-17, 0, 0]~, [1, -18, 0]~, [1, 0, -18]~], [Vecsmall([]), V ecsmall([]), Vecsmall([])], [1/9, 0, 0; 0, 1/9, 0; 0, 0, 1/9]]], [[], [], [] ]], [468, -77, 0, 728, -546, 0, 546, 0; 0, 0, 1, 0, -2, -6, 0, -6; 0, 1, 0, -1, 1, 0, -3, 3]] ? 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, 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]]] ? 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, 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]]] ? 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,[as,[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 - 6*x^3 + 6*x^2 + 13*x - 5, x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1, x^5 - x^4 + 4*x^3 - 2*x^2 + x - 1, x^5 + 4*x^3 - 4*x^2 + 8*x - 8] ? polred(x^4-28*x^3-458*x^2+9156*x-25321,3) [1 x - 1] [1/115*x^2 - 14/115*x - 327/115 x^2 - 10] [2/897*x^3 - 14/299*x^2 - 1171/897*x + 9569/897 x^4 - 32*x^2 + 6] [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 - 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 + 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 - 2*x^4 - 62*x^3 + 85*x^2 + 818*x + 1, x^5 - 2*x^4 - 53*x^3 - 46 *x^2 + 508*x + 913, x^5 - 2*x^4 - 13*x^3 + 37*x^2 - 21*x - 1, x^5 - x^4 - 52 *x^3 - 197*x^2 - 273*x - 127] ? polred(p2,1,fa) [x - 1, x^5 - 2*x^4 - 62*x^3 + 85*x^2 + 818*x + 1, x^5 - 2*x^4 - 53*x^3 - 46 *x^2 + 508*x + 913, x^5 - 2*x^4 - 13*x^3 + 37*x^2 - 21*x - 1, x^5 - x^4 - 52 *x^3 - 197*x^2 - 273*x - 127] ? 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 - 363*x - 2663, 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.091666666666666666666666666666666666668 ? zetak(nfz,1.5+3*I) 0.88324345992059326405525724366416928892 - 0.2067536250233895222724230899142 7938853*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(283, 31285, -18771, 0.E-57)], 2800.625251907016076486370621737 0745514] ? sizebyte(%) 288 ? getheap [175, 102929] ? print("Total time spent: ",gettime); Total time spent: 84 pari-2.5.5/src/test/64/rnfkummer0000644000175000017500000002476512147140047015052 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 + (11010816910061886417185719809710030865163 3373991261854661897473896921309979584250845786*y^3 + 13806138974474240148915 4687510692802021389570171865180798324014776069968837855846155006*y^2 + 16799 6969256083616948098067771364784531799531979188608550686948762405801602633145 257038*y - 15369464355240028579717755753147582045026488056242331352968676744 4129838100365080190135) 2 x^3 + (19710886507130683637499481853346220*y^3 - 276380637484283870500207144 441368652*y^2 + 321806883259334223558938029085301164*y - 2893764851921508720 91555008989630209)*x + (-623440420006991409263578197892153490708780082196500 5*y^3 + 87417103564909472118499724747251035776212296637996160*y^2 - 10178508 1248253577808797714025930280347744436431138133*y + 9152759182245610297667105 1455070193926146359966708289) 3 x^5 + (-331787058087433622201490395582174260626191743561925/229919*y^3 - 127 70590263087881493273666791720172143285966373266850/229919*y^2 + 252530864067 347909495461855214867697325712170338053625/229919*y + 8545812265626423170117 078769382358637678369854706286990/229919)*x^3 + (741137384735896583917824566 9124241722802355845940782056765103016169253667483036742031571549849399425/22 9919*y^3 + 29908945080051595226543486406824904032006190612955218156914517507 4111867505102027879635068320637066600/229919*y^2 - 5427673470715491933831700 5016773634128825024048285936838150337968646533142409934071587113873717083663 75/229919*y - 20633401923387519441198186160203919441250546265727911426620743 5419118122791996003199652251159881598125045/229919)*x + (-763802043902610266 0372620956975735402523048908173456217998657436248191916844762375838667413775 327493758676186821213721110700/229919*y^3 - 30862103817326494707711384774860 0337923623765969810572164024716852039554549314676411675083217634932908121993 533001562805058390/229919*y^2 + 55877136271096874316033083745287434938352875 2001891555722891568975034278194627285980845922565260674387779415413680299407 1229770/229919*y + 213074103176749065348658475404522950187461734399857485188 812977585625860464126648103529066067410800528044936919772101513914073720/229 919) 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 - 4633910*x^3 - 352959211304163606080220*x^2 + 4110573092104718915163940 5743785*x + 1252389138034185331199768653982538252594094777596 7 x^3 + (-240*y^5 + 594*y^4 - 1002*y^3 + 474*y^2 - 462*y - 504)*x + (528*y^5 - 1340*y^4 + 2302*y^3 - 1230*y^2 + 1174*y + 966) 8 x^5 + (-12490585381661544359255403301035053110061910*y^3 + 88753785204045614 72503422910872004290197460*y^2 + 6432039127327618730502928086755494337371796 10*y - 457038484130159980782436350930533714409061170)*x^3 + (-13402751428164 5340620300162483056350640850689292892267066826165512*y^3 + 95235243030030469 814112992330493778292557062830362488860799262053*y^2 + 690175992472503337590 1003506523314713919218011682438894990413482822*y - 4904148131739972327284545 793455166015180538153351582525198684659988)*x^2 + (-473979575575708881557088 56849994683849365520972511563824369572802678417823703951003630*y^3 + 3367932 3468496441220407209890566679520252152888549909181980050360738580514765560899 830*y^2 + 244076244894932600669105503748523340880310818979111099033902755459 2708168372793653934980*y - 1734320048033240933678067521047553381449799255523 887315704756124974424249211251806055445)*x + (888479132132125436437249142813 7413743146658454713780078075413546969837635616890304615115722308289473248381 8/5*y^3 - 631322057494452864618221700953863619523020575841378253933498629374 80952856334509099209369622841067534904427/5*y^2 - 45752319596243710576653560 1831075687685136958790100077326575099623318014513223892050404458305737184896 9400608/5*y + 32509990947484580403420755703092054732352560997472944663250483 78505864671503910959921397017511503388596960342/5) 9 x^3 + (-13512473865*y - 491304352371)*x + (1710942834201925*y + 622087144601 41926) 10 [x^3 + (-13512473865*y - 491304352371)*x + (-3356312100136324*y - 1220332187 06666997), x^3 + (-13512473865*y - 491304352371)*x + (1710942834201925*y + 6 2208714460141926), x^3 + (-13512473865*y - 491304352371)*x + (-5067254934338 249*y - 184241933166808923), x^3 - 3*x - 1] 11 x^5 - 10*x^3 + 20*x - 10 12 x^5 + (-4765941654868705920419593586878703269747443910292761667320/27*y^3 + 12377326963957769050169907799449802342616696593025278899880/27*y^2 + 9156375 4885043941876415000407442717910425544656584846908340/9*y - 69807413945909958 737090271240415146410317575079258649322980)*x^3 + (6451423090654457168258951 1351194450977164685449063098341641014670970987121547620768780/9*y^3 + 103888 5056939392143713886860303958374052024030744377976499254396211420837339260930 810730/9*y^2 + 7204576455294605320326104107342502483034902918239860127912033 50054151620992606858871040/3*y - 1949894339462550414934793879044197752851790 591620384696794570917612757675449488363778600)*x^2 + (3929295632822200815394 4803898489098128932032711550031730063444615456140056033652549074845456512471 411557758171410640/27*y^3 - 427972943345232137254913592671796727387567339451 65906036022185601826401891828657319973423738492464889809977337918730/27*y^2 - 58543936970899598172689704955617487044917082842108787996682681590606962124 0862081918848885137716222874222290434775860/9*y + 56758393921634675144943829 2125138096368610480521936480792433645673756696626324467760639279905138193353 501265459913630)*x + (-16588030084529273591749178628751783192593636062035926 3001581020460775240894723792010012760998422025119354978561747025310567908752 7217460110810154/27*y^3 - 38763841693484466059812330019519221076969732238673 8868860366528309211208861285467317969333279480995134477537152824954995739700 93980855830078159538/27*y^2 - 4843681866419016675318397390866680005599281490 6499946012258935482509582740111081439335464648592560089680906815045944138600 424070469912034951983348/9*y + 224216371038354157705777604673561016608169911 7007545534864995433938954691615603308177626247037067218367597753762959239283 9341371309530971255421334) 13 x^5 + (-41675749815605474682300*y - 473011239937199627294510)*x^3 + (-129874 08509128761747208433824766580*y - 114459000172186730474768920840594100)*x^2 + (1901303847876681901370591794176695615698424100*y + 1803279733796267725648 6556095959141093737663985)*x + (50994788340520140686216889164131759223136164 496558335484*y + 448064359589646139039961812179554933382541180905578823300) 14 x^2 + (824026557672831281950311056753718476697259961292*y^5 - 15179349593008 713856670944676145084598171515030460*y^4 - 178539391809162810015652795214212 41357962256007037*y^3 - 15282535320519140011899705740411367887125545357568*y ^2 - 21209795397772589502818948708670314639663140114801*y - 2134588654801758 4384636582343163931788574804900033) 15 x^2 + (y - 1) 16 x^2 + (30237893533377177585274818309716447175*y^5 - 332498313903387415829914 313666675360297*y^4 + 58935557047612851360265142086661442617*y^3 - 117640120 973960296978686942015897120823*y^2 + 113867586930627879387621746872715126816 *y - 257526772651124939007698567207659716875) 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 + (4973/2*y^3 + 36285*y^2 - 107 6961/2*y + 2121130) 20 [x^3 - 3*x - 1] Total time spent: 14992 pari-2.5.5/src/test/64/analyz0000644000175000017500000000033412147140047014324 0ustar billbill echo = 1 (on) ? gettime;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)); ? getheap [6, 50] ? print("Total time spent: ",gettime); Total time spent: 16 pari-2.5.5/src/test/64/elliptic0000644000175000017500000001651012147140047014636 0ustar billbill echo = 1 (on) ? gettime;ellinit([0,0,0,-1,0]) [0, 0, 0, -1, 0, 0, -2, 0, -1, 48, 0, 64, 1728, [1.0000000000000000000000000 000000000000, 0.E-57, -1.0000000000000000000000000000000000000]~, 2.62205755 42921198104648395898911194137, -2.6220575542921198104648395898911194137*I, 1 .1981402347355922074399224922803238782, 1.1981402347355922074399224922803238 782*I, 6.8751858180203728274900957798105571979] ? ellinit([0,0,0,-17,0],1) [0, 0, 0, -17, 0, 0, -34, 0, -289, 816, 0, 314432, 1728] ? 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, [0.83756543528332303 544481089907503024040, 0.26959443640544455826293795134926000405, -1.10715987 16887675937077488504242902445]~, 2.9934586462319596298320099794525081778, -2 .4513893819867900608542248318665252254*I, 0.94263855591362295176518779416067 539931, 1.3270305788796764757190502098362372906*I, 7.33813274078957673907072 10033323055880] ? 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, [-0.1624345647 1667696455518910092496975960, -0.73040556359455544173706204865073999595, -2. 1071598716887675937077488504242902445]~, -2.99345864623195962983200997945250 81778, 2.4513893819867900608542248318665252254*I, -0.94263855591362295176518 779416067539931, -1.3270305788796764757190502098362372906*I, 7.3381327407895 767390707210033323055880] ? apoint=ellchangepoint(apoint,[-1,1,2,3]) [1, 3] ? ellisoncurve(acurve,apoint) 1 ? ellglobalred(acurve) [37, [1, -1, 2, 2], 1] ? ellheight(acurve,apoint) 0.81778253183950144377417759611107234575 ? ellheight(acurve,apoint,1) 0.81778253183950144377417759611107234576 ? ellordinate(acurve,1) [8, 3] ? ellpointtoz(acurve,apoint) 0.72491221490962306778878739838332384646 + 7.589868072444759051 E-59*I ? ellztopoint(acurve,%) [0.99999999999999999999999999999999999994 - 3.794934036222379527 E-58*I, 2.9 999999999999999999999999999999999998 + 0.E-37*I] ? ellpow(acurve,apoint,10) [-28919032218753260057646013785951999/292736325329248127651484680640160000, 478051489392386968218136375373985436596569736643531551/158385319626308443937 475969221994173751192384064000000] ? ellwp(acurve,,,32) 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([0,0,0,-3,0]) [0, 0, 0, -3, 0, 0, -6, 0, -9, 144, 0, 1728, 1728, [1.7320508075688772935274 463415058723669, 0.E-57, -1.7320508075688772935274463415058723669]~, 1.99233 28995834907073368080310227454215, -1.9923328995834907073368080310227454215*I , 1.5768412268083121362312158419045774608, 1.5768412268083121362312158419045 774608*I, 3.9693903827627596663162680332564652025] ? 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, [0.8375654352833230 3544481089907503024040, 0.26959443640544455826293795134926000405, -1.1071598 716887675937077488504242902445]~, 2.9934586462319596298320099794525081778, - 2.4513893819867900608542248318665252254*I, 0.9426385559136229517651877941606 7539931, 1.3270305788796764757190502098362372906*I, 7.3381327407895767390707 210033323055880] ? l=elllseries(ccurve,2) 0.38157540826071121129371040958008663664 ? elllseries(ccurve,2,1.2)-l 2.292213984103460641 E-37 ? tcurve=ellinit([1,0,1,-19,26]); ? ellorder(tcurve,[1,2]) 6 ? elltors(tcurve) [12, [6, 2], [[-2, 8], [3, -2]]] ? mcurve=ellinit([0,0,0,-17,0]) [0, 0, 0, -17, 0, 0, -34, 0, -289, 816, 0, 314432, 1728, [4.1231056256176605 498214098559740770251, 0.E-57, -4.1231056256176605498214098559740770251]~, 1 .2913084409290072207105564235857096010, -1.291308440929007220710556423585709 6010*I, 2.4328754881596176532948539893637583869, 2.4328754881596176532948539 893637583869*I, 1.6674774896145033307120230298772362382] ? 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, [2.000000000000 0000000000000000000000000, -0.62500000000000000000000000000000000000 + 0.330 71891388307382381270196920490755321*I, -0.6250000000000000000000000000000000 0000 - 0.33071891388307382381270196920490755321*I]~, 1.933311705616811546733 0768390298137311, -0.96665585280840577336653841951490686553 - 2.557530989916 0994790492257969408742850*I, 1.7116972661997117051282981581331545224 - 8.816 207631167156310 E-39*I, -0.85584863309985585256414907906657726121 + 0.985597 14813873164489992761459498878368*I, 4.9445046002825467364981969681843776445] ? ellpow(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))] ? \p96 realprecision = 96 significant digits ? precision(cmcurve) 38 ? getheap [57, 4395] ? print("Total time spent: ",gettime); Total time spent: 12 pari-2.5.5/src/test/64/bnfisintnorm0000644000175000017500000012166712147140047015553 0ustar billbill echo = 1 (on) ? setrand(1);bnf=bnfinit(x^2+105); ? for(i=1,1000,do(i)) 1: [1] 4: [2] 9: [3] 16: [4] 25: [5] 36: [6] 49: [7] 64: [8] 81: [9] 100: [10] 105: [x] 106: [x + 1, x - 1] 109: [x + 2, x - 2] 114: [x + 3, x - 3] 121: [x + 4, -11, x - 4] 130: [x + 5, x - 5] 141: [x + 6, x - 6] 144: [12] 154: [x - 7, -x - 7] 169: [x - 8, -13, x + 8] 186: [x + 9, x - 9] 196: [14] 205: [x + 10, x - 10] 225: [15] 226: [x + 11, x - 11] 249: [x + 12, x - 12] 256: [16] 274: [x + 13, x - 13] 289: [17] 301: [x + 14, x - 14] 324: [18] 330: [-x - 15, x - 15] 361: [x - 16, -19, x + 16] 394: [x + 17, x - 17] 400: [20] 420: [2*x] 421: [-2*x + 1, -2*x - 1] 424: [2*x + 2, 2*x - 2] 429: [-2*x + 3, -x + 18, -x - 18, -2*x - 3] 436: [2*x + 4, 2*x - 4] 441: [21] 445: [-2*x + 5, 2*x + 5] 456: [2*x + 6, 2*x - 6] 466: [x + 19, x - 19] 469: [-2*x + 7, 2*x + 7] 484: [2*x + 8, 22, 2*x - 8] 501: [-2*x + 9, 2*x + 9] 505: [x + 20, x - 20] 520: [2*x + 10, 2*x - 10] 529: [23] 541: [-2*x + 11, 2*x + 11] 546: [-x + 21, x + 21] 564: [2*x + 12, 2*x - 12] 576: [24] 589: [2*x - 13, -x - 22, x - 22, -2*x - 13] 616: [2*x - 14, -2*x - 14] 625: [25] 634: [x + 23, x - 23] 645: [2*x - 15, -2*x - 15] 676: [2*x - 16, -26, 2*x + 16] 681: [x + 24, x - 24] 709: [-2*x + 17, 2*x + 17] 729: [27] 730: [x + 25, x - 25] 744: [2*x + 18, 2*x - 18] 781: [x + 26, -2*x - 19, 2*x - 19, x - 26] 784: [28] 820: [2*x + 20, 2*x - 20] 834: [x + 27, x - 27] 841: [29] 861: [2*x - 21, -2*x - 21] 889: [x + 28, x - 28] 900: [30] 904: [2*x + 22, 2*x - 22] 945: [3*x] 946: [x - 29, -3*x - 1, -3*x + 1, x + 29] 949: [3*x + 2, -2*x - 23, 2*x - 23, -3*x + 2] 954: [3*x + 3, 3*x - 3] 961: [-3*x + 4, -31, 3*x + 4] 970: [-3*x - 5, 3*x - 5] 981: [3*x + 6, 3*x - 6] 994: [3*x + 7, 3*x - 7] 996: [2*x + 24, 2*x - 24] ? setrand(1);bnf=bnfinit(x^2-65); ? for(i=1,1000,do(i-500)) -491: [-6*x - 43, 6*x - 43] -490: [-13/2*x - 95/2, 7/2*x - 35/2, 37/2*x + 295/2, -53/2*x - 425/2, 7/2*x + 35/2, 157/2*x + 1265/2] -485: [3*x - 10, -3*x - 10] -484: [-11/2*x - 77/2, 22*x + 176, -11/2*x + 77/2] -481: [7*x + 52, 71*x + 572] -469: [-5*x + 34, -43*x - 346, 11*x + 86, 5*x + 34] -464: [99/2*x + 797/2, -15/2*x - 113/2, -3*x + 11, 15*x - 119, 4*x + 24, -4* x + 24, -15*x - 119, 3*x + 11, 127/2*x + 1023/2, -19/2*x - 147/2] -454: [73/2*x + 587/2, -7/2*x - 37/2, -7/2*x + 37/2, 25/2*x + 197/2] -446: [51/2*x + 409/2, 9/2*x + 59/2, -9/2*x + 59/2, -35/2*x - 279/2] -441: [-3*x + 12, 21*x + 168, 3*x + 12] -439: [-56*x - 451, -8*x - 61] -419: [30*x + 241, 14*x + 111] -416: [-279/2*x - 2249/2, 3*x + 13, -10*x - 78, 42*x + 338, -179*x - 1443, 7 /2*x + 39/2] -415: [4*x + 25, -4*x + 25] -406: [155/2*x + 1249/2, -23/2*x - 181/2, -17/2*x - 131/2, 5/2*x - 1/2, -5/2 *x - 1/2, 17/2*x - 131/2, 71/2*x + 571/2, -11/2*x - 79/2] -404: [5/2*x + 3/2, -33/2*x - 263/2, -6*x - 44, 6*x - 44, 49/2*x + 393/2, -5 /2*x + 3/2] -400: [5/2*x - 5/2, -5*x - 35, 20*x + 160, -85*x - 685, 5/2*x + 5/2] -394: [-125/2*x - 1007/2, 5/2*x + 7/2, 5/2*x - 7/2, -13/2*x - 97/2] -389: [-3*x + 14, 3*x + 14] -386: [185/2*x + 1491/2, 5/2*x - 9/2, -5/2*x - 9/2, -9/2*x - 61/2] -376: [5/2*x + 11/2, 7/2*x + 41/2, -7*x - 53, -13*x - 103, 29*x + 233, 7*x - 53, -247/2*x - 1991/2, -5/2*x + 11/2] -365: [9*x + 70, -41*x - 330] -364: [-437/2*x - 3523/2, 47/2*x + 377/2, 4*x + 26, -100*x - 806, -31/2*x - 247/2, 5/2*x + 13/2] -361: [19*x + 152] -360: [69/2*x + 555/2, 3*x - 15, 3*x + 15, 21/2*x + 165/2] -350: [5/2*x + 15/2, -95/2*x - 765/2, -15/2*x - 115/2, 5/2*x - 15/2] -335: [28*x + 225, -12*x - 95] -334: [5/2*x - 17/2, -215/2*x - 1733/2, -7/2*x - 43/2, 5/2*x + 17/2] -329: [3*x + 16, 5*x + 36, -69*x - 556, -3*x + 16] -326: [-11/2*x - 81/2, -29/2*x - 231/2, 45/2*x + 361/2, 11/2*x - 81/2] -324: [-9/2*x - 63/2, 18*x + 144, -9/2*x + 63/2] -316: [-19/2*x - 149/2, -5/2*x - 19/2, 40*x + 322, 8*x + 62, -5/2*x + 19/2, -19/2*x + 149/2] -315: [54*x + 435, 6*x + 45] -311: [-4*x + 27, 4*x + 27] -296: [-5/2*x + 21/2, -13/2*x - 99/2, 3*x + 17, 27*x + 217, -11*x - 87, -3*x + 17, 93/2*x + 749/2, 5/2*x + 21/2] -290: [43/2*x + 345/2, -7/2*x - 45/2, 183/2*x + 1475/2, -27/2*x - 215/2] -289: [17*x + 136] -274: [5/2*x + 23/2, -65/2*x - 523/2, -17/2*x - 133/2, 5/2*x - 23/2] -269: [7*x + 54, 39*x + 314] -261: [3*x + 18, -3*x + 18] -260: [121/2*x + 975/2, 2*x, 9/2*x + 65/2] -259: [-2*x + 1, -10*x - 79, 26*x + 209, 2*x + 1] -256: [25/2*x + 199/2, -5*x + 37, 2*x - 2, -4*x - 28, 16*x + 128, -4*x + 28, 2*x + 2, -5*x - 37, 41/2*x + 329/2] -251: [2*x - 3, -2*x - 3] -250: [5/2*x - 25/2, 5/2*x + 25/2] -244: [-151/2*x - 1217/2, 91/2*x + 733/2, 2*x + 4, -2*x + 4, -11/2*x - 83/2, 7/2*x + 47/2] -235: [2*x - 5, -2*x - 5] -234: [-15/2*x - 117/2, 63/2*x + 507/2] -225: [15*x + 120] -224: [39/2*x + 313/2, -5/2*x - 27/2, -3*x + 19, 9*x + 71, 2*x + 6, -38*x - 306, -6*x - 46, 2*x - 6, 25*x + 201, -3*x - 19, -5/2*x + 27/2, 23/2*x + 183/ 2] -211: [2*x - 7, -2*x - 7] -199: [-4*x - 29, 4*x - 29] -196: [61/2*x + 491/2, -7/2*x - 49/2, -181/2*x - 1459/2, -2*x + 8, 14*x + 11 2, 2*x + 8, 5/2*x + 29/2, -7/2*x + 49/2, -13/2*x - 101/2] -194: [-9/2*x - 67/2, -21/2*x - 167/2, 37/2*x + 297/2, 9/2*x - 67/2] -191: [24*x + 193, 8*x + 63] -185: [-3*x + 20, 3*x + 20] -181: [-5*x - 38, -37*x - 298] -179: [-2*x + 9, 2*x + 9] -169: [13*x + 104] -166: [35/2*x + 281/2, 5/2*x + 31/2, -5/2*x + 31/2, -19/2*x - 151/2] -160: [11/2*x + 85/2, 23*x + 185, 2*x - 10, 2*x + 10, 7*x + 55, 59/2*x + 475 /2] -146: [-87/2*x - 701/2, -3/2*x - 1/2, 3/2*x - 1/2, 7/2*x + 51/2] -144: [3/2*x - 3/2, -3*x - 21, 12*x + 96, -51*x - 411, 3/2*x + 3/2] -140: [-17/2*x - 135/2, 3/2*x + 5/2, 36*x + 290, 4*x + 30, -3/2*x + 5/2, 33/ 2*x + 265/2] -139: [2*x - 11, -2*x - 11] -134: [3/2*x - 7/2, 117/2*x + 943/2, -5/2*x - 33/2, -3/2*x - 7/2] -131: [22*x + 177, 6*x + 47] -126: [3/2*x + 9/2, -57/2*x - 459/2, -9/2*x - 69/2, 3/2*x - 9/2] -121: [11*x + 88] -116: [-211/2*x - 1701/2, 31/2*x + 249/2, 2*x + 12, -2*x + 12, -15/2*x - 119 /2, 3/2*x + 11/2] -104: [3/2*x + 13/2, -5*x - 39, 21*x + 169, -179/2*x - 1443/2] -101: [-3*x - 22, 3*x - 22] -100: [-5/2*x - 35/2, 10*x + 80, -5/2*x + 35/2] -94: [-7/2*x - 53/2, -13/2*x - 103/2, 29/2*x + 233/2, 7/2*x - 53/2] -91: [2*x + 13, -50*x - 403] -90: [3/2*x - 15/2, 3/2*x + 15/2] -81: [9*x + 72] -79: [20*x + 161, 4*x + 31] -74: [3/2*x + 17/2, 27/2*x + 217/2, -11/2*x - 87/2, -3/2*x + 17/2] -65: [x] -64: [-5/2*x + 37/2, x - 1, -2*x - 14, 8*x + 64, -34*x - 274, x + 1, -5/2*x - 37/2] -61: [x + 2, -x + 2] -56: [-3/2*x + 19/2, 9/2*x + 71/2, x + 3, -19*x - 153, -3*x - 23, x - 3, 25/ 2*x + 201/2, -3/2*x - 19/2] -49: [-x + 4, 7*x + 56, x + 4] -40: [23/2*x + 185/2, x - 5, x + 5, 7/2*x + 55/2] -36: [-3/2*x - 21/2, 6*x + 48, -3/2*x + 21/2] -35: [18*x + 145, 2*x + 15] -29: [x + 6, -x + 6] -26: [-5/2*x - 39/2, 21/2*x + 169/2] -25: [5*x + 40] -16: [1/2*x - 1/2, -x - 7, 4*x + 32, -17*x - 137, 1/2*x + 1/2] -14: [1/2*x + 3/2, -19/2*x - 153/2, -3/2*x - 23/2, 1/2*x - 3/2] -10: [1/2*x - 5/2, 1/2*x + 5/2] -9: [3*x + 24] -4: [-1/2*x - 7/2, 2*x + 16, -1/2*x + 7/2] -1: [x + 8] 0: [0] 1: [1] 4: [-15/2*x - 121/2, 2, -1/2*x - 9/2] 9: [3] 10: [3/2*x + 25/2, 13/2*x + 105/2] 14: [11/2*x + 89/2, -1/2*x - 11/2, 1/2*x - 11/2, 5/2*x + 41/2] 16: [7/2*x + 57/2, x - 9, 4, -x - 9, 9/2*x + 73/2] 25: [5] 26: [-79/2*x - 637/2, 1/2*x + 13/2] 29: [14*x + 113, -2*x - 17] 35: [x + 10, -x + 10] 36: [-45/2*x - 363/2, 6, -3/2*x - 27/2] 40: [1/2*x + 15/2, 3*x + 25, 13*x + 105, -1/2*x + 15/2] 49: [-4*x - 33, 7, 12*x + 97] 56: [-5/2*x - 43/2, -1/2*x + 17/2, 11*x + 89, -x - 11, x - 11, 5*x + 41, 1/2 *x + 17/2, -43/2*x - 347/2] 61: [10*x + 81, -6*x - 49] 64: [-3/2*x - 29/2, 7*x + 57, 2*x - 18, 8, -2*x - 18, 9*x + 73, -77/2*x - 62 1/2] 65: [8*x + 65] 74: [41/2*x + 331/2, 1/2*x + 19/2, 1/2*x - 19/2, -7/2*x - 59/2] 79: [x + 12, -x + 12] 81: [9] 90: [9/2*x + 75/2, 39/2*x + 315/2] 91: [29*x + 234, -3*x - 26] 94: [-109/2*x - 879/2, 1/2*x - 21/2, 1/2*x + 21/2, 3/2*x + 31/2] 100: [-75/2*x - 605/2, 10, -5/2*x - 45/2] 101: [-46*x - 371, 2*x + 19] 104: [37/2*x + 299/2, -79*x - 637, x + 13, -11/2*x - 91/2] 116: [-13/2*x - 107/2, 1/2*x + 23/2, 28*x + 226, -4*x - 34, 1/2*x - 23/2, -1 3/2*x + 107/2] 121: [11] 126: [33/2*x + 267/2, -3/2*x - 33/2, 3/2*x - 33/2, 15/2*x + 123/2] 131: [x + 14, -x + 14] 134: [17/2*x + 139/2, 7/2*x + 61/2, 7/2*x - 61/2, -31/2*x - 251/2] 139: [5*x + 42, -27*x - 218] 140: [1/2*x - 25/2, 29/2*x + 235/2, 2*x + 20, -2*x + 20, -19/2*x - 155/2, 1/ 2*x + 25/2] 144: [21/2*x + 171/2, 3*x - 27, 12, -3*x - 27, 27/2*x + 219/2] 146: [-5/2*x - 47/2, -25/2*x - 203/2, 23/2*x + 187/2, -5/2*x + 47/2] 160: [-3/2*x + 35/2, x + 15, 6*x + 50, 26*x + 210, -x + 15, 3/2*x + 35/2] 166: [1/2*x + 27/2, 71/2*x + 573/2, -9/2*x - 77/2, 1/2*x - 27/2] 169: [13] 179: [-7*x - 58, 25*x + 202] 181: [2*x - 21, -2*x - 21] 185: [-4*x - 35, 44*x + 355] 191: [x + 16, -x + 16] 194: [-139/2*x - 1121/2, 1/2*x - 29/2, 1/2*x + 29/2, 5/2*x + 49/2] 196: [3/2*x + 37/2, 7/2*x - 63/2, -11/2*x - 93/2, -8*x - 66, 14, 24*x + 194, -11/2*x + 93/2, -7/2*x - 63/2, 3/2*x - 37/2] 199: [-61*x - 492, 3*x + 28] 211: [9*x + 74, -23*x - 186] 224: [1/2*x + 31/2, -67/2*x - 541/2, -5*x - 43, -x + 17, 22*x + 178, -2*x - 22, 2*x - 22, 10*x + 82, x + 17, -43*x - 347, -13/2*x - 109/2, -1/2*x + 31/2 ] 225: [15] 234: [-237/2*x - 1911/2, 3/2*x + 39/2] 235: [11*x + 90, -21*x - 170] 244: [-9/2*x - 79/2, 5/2*x + 51/2, 20*x + 162, -12*x - 98, 5/2*x - 51/2, -9/ 2*x + 79/2] 250: [15/2*x + 125/2, 65/2*x + 525/2] 251: [13*x + 106, -19*x - 154] 256: [-1/2*x + 33/2, -3*x - 29, 14*x + 114, -60*x - 484, 16, -4*x - 36, 18*x + 146, -77*x - 621, 1/2*x + 33/2] 259: [-15*x - 122, x - 18, x + 18, 17*x + 138] 260: [7/2*x + 65/2, 16*x + 130, 137/2*x + 1105/2] 261: [42*x + 339, -6*x - 51] 269: [-2*x + 23, 2*x + 23] 274: [63/2*x + 509/2, -3/2*x - 41/2, 3/2*x - 41/2, 17/2*x + 141/2] 289: [17] 290: [1/2*x + 35/2, 11/2*x - 95/2, 11/2*x + 95/2, 1/2*x - 35/2] 296: [-19/2*x - 157/2, 5/2*x - 53/2, 41*x + 331, x + 19, x - 19, -7*x - 59, 5/2*x + 53/2, 61/2*x + 493/2] 311: [-5*x - 44, 59*x + 476] 315: [3*x + 30, -3*x + 30] 316: [-301/2*x - 2427/2, -59/2*x - 477/2, 2*x + 24, -2*x + 24, -21/2*x - 173 /2, -3/2*x - 43/2] 324: [-135/2*x - 1089/2, 18, -9/2*x - 81/2] 326: [-169/2*x - 1363/2, 1/2*x - 37/2, 1/2*x + 37/2, 7/2*x + 67/2] 329: [40*x + 323, -4*x + 37, -4*x - 37, -8*x - 67] 334: [23/2*x + 189/2, -13/2*x - 111/2, 13/2*x - 111/2, 57/2*x + 461/2] 335: [x + 20, x - 20] 350: [55/2*x + 445/2, -5/2*x - 55/2, 5/2*x - 55/2, 25/2*x + 205/2] 360: [3/2*x + 45/2, 9*x + 75, 39*x + 315, -3/2*x + 45/2] 361: [19] 364: [-27/2*x - 221/2, 1/2*x + 39/2, 58*x + 468, -6*x - 52, -495/2*x - 3991/ 2, 53/2*x + 429/2] 365: [-2*x + 25, -2*x - 25] 376: [51/2*x + 413/2, -15/2*x + 127/2, -109*x - 879, x - 21, x + 21, 3*x + 3 1, -15/2*x - 127/2, -29/2*x - 237/2] 386: [11/2*x + 97/2, 31/2*x + 253/2, -49/2*x - 397/2, 11/2*x - 97/2] 389: [-10*x - 83, 38*x + 307] 394: [-7/2*x - 69/2, 47/2*x + 381/2, 33/2*x + 269/2, 7/2*x - 69/2] 400: [35/2*x + 285/2, 5*x - 45, 20, -5*x - 45, 45/2*x + 365/2] 404: [43/2*x + 349/2, 1/2*x - 41/2, -92*x - 742, 4*x + 38, 1/2*x + 41/2, -37 /2*x - 301/2] 406: [9/2*x + 83/2, 3/2*x - 47/2, -267/2*x - 2153/2, 39/2*x + 317/2, -41/2*x - 333/2, 5/2*x + 57/2, 3/2*x + 47/2, 9/2*x - 83/2] 415: [57*x + 460, -7*x - 60] 416: [-17/2*x - 143/2, 37*x + 299, -158*x - 1274, 2*x + 26, -11*x - 91, 95/2 *x + 767/2] 419: [x + 22, -x + 22] 439: [-3*x - 32, 3*x - 32] 441: [-12*x - 99, 21, 36*x + 291] 446: [1/2*x + 43/2, 131/2*x + 1057/2, -13/2*x - 113/2, 1/2*x - 43/2] 454: [3/2*x + 49/2, -93/2*x - 751/2, -19/2*x - 159/2, -3/2*x + 49/2] 464: [5/2*x + 59/2, 7/2*x - 71/2, -13*x - 107, x + 23, 56*x + 452, -8*x - 68 , -239*x - 1927, 35*x + 283, 7/2*x + 71/2, 5/2*x - 59/2] 469: [-6*x - 53, -2*x - 27, -2*x + 27, 74*x + 597] 481: [108*x + 871, 4*x + 39] 484: [-165/2*x - 1331/2, 22, -11/2*x - 99/2] 485: [14*x + 115, -34*x - 275] 490: [9/2*x - 85/2, 21/2*x + 175/2, -1/2*x + 45/2, -1/2*x - 45/2, 91/2*x + 7 35/2, 9/2*x + 85/2] 491: [-91*x - 734, 5*x + 46] ? setrand(1);bnf=bnfinit(x^5-37); ? for(i=1,1000,do(i-500)) -499: [-2374*x^4 + 1671*x^3 + 4497*x^2 - 22065*x + 54444] -497: [-3457*x^4 + 2824*x^3 + 15097*x^2 + 751*x - 76402, -10*x^4 - 5*x^3 + 9 *x^2 - 23*x - 182, -x^3 + 2*x^2 - 5*x + 3] -496: [-33*x^4 + 31*x^3 + 177*x^2 + 89*x - 647, 306*x^4 + 1960*x^3 + 1005*x^ 2 - 7425*x - 14522] -494: [-6*x^4 + 14*x^3 - 21*x^2 + 11*x + 52] -491: [1888*x^4 + 8569*x^3 + 2900*x^2 - 32636*x - 53824, 6486*x^4 - 17022*x^ 3 + 29212*x^2 - 25158*x - 40023, -1027*x^4 - 866*x^3 + 3228*x^2 + 7730*x - 3 948] -490: [-2*x^4 + 3*x^3 - 2*x^2 - 7*x + 30] -487: [-5668*x^4 + 14258*x^3 - 23472*x^2 + 17752*x + 40361] -486: [-528345*x^4 + 15834*x^3 + 2186994*x^2 - 7352895*x + 15224466] -483: [21*x^4 + 4*x^3 - 84*x^2 - 124*x + 198] -481: [-6*x^4 + 20*x^3 - 41*x^2 + 52*x] -478: [x^3 + x^2 - 3*x - 9] -477: [-3*x^4 - 6*x^3 - 12*x^2 - 25*x - 53] -476: [-149520*x^4 + 433375*x^3 + 1184038*x^2 - 333085*x - 5448548] -475: [28292*x^4 + 18315*x^3 - 96637*x^2 - 200626*x + 154333] -474: [-38962*x^4 - 243483*x^3 + 976308*x^2 - 2220316*x + 3258047] -468: [-6*x^4 + 26*x^3 - 61*x^2 + 93*x - 52] -466: [-1159032*x^4 - 2381161*x^3 - 4715244*x^2 - 9491919*x - 20062122] -465: [-2*x^4 - 4*x^3 - 9*x^2 - 20*x - 40, -x^2 + x - 3, -4609*x^4 - 1282*x^ 3 + 17907*x^2 + 28221*x - 40000, 4156*x^4 + 116355*x^3 + 130442*x^2 - 327263 *x - 969403] -463: [11*x^4 - 5*x^3 - 30*x^2 + 121*x - 276] -461: [x^4 - 2*x^3 + 3*x^2 - 4*x - 5] -457: [87*x^4 + 185*x^3 - 134*x^2 - 956*x - 651] -455: [-2*x^4 - 4*x^3 - 6*x^2 - 10*x - 27] -454: [-42409*x^4 - 90034*x^3 + 479719*x^2 - 1216471*x + 2018953] -452: [17*x^4 - 280*x^3 + 858*x^2 - 1677*x + 1938] -450: [14171*x^4 - 24148*x^3 - 90804*x^2 - 13185*x + 368144] -448: [-4174*x^4 - 4308*x^3 + 32046*x^2 - 88496*x + 158968, -48*x^4 + 86*x^3 - 83*x^2 - 88*x + 645] -447: [-3023*x^4 + 8573*x^3 + 23724*x^2 - 6154*x - 108401] -446: [-3334966*x^4 + 10447057*x^3 - 20665939*x^2 + 24559864*x + 5787442] -443: [52874*x^4 + 359697*x^3 + 233432*x^2 - 1228056*x - 2552814] -442: [-72646*x^4 + 242032*x^3 - 498349*x^2 + 634190*x - 161] -441: [x^3 + x^2 - 2*x - 9] -439: [-340*x^4 + 658*x^3 - 751*x^2 - 288*x + 4142] -435: [-2*x^3 - 5*x^2 - 3*x + 7] -434: [-229020*x^4 + 2937*x^3 + 961070*x^2 - 3214168*x + 6633571] -426: [307*x^4 - 457*x^3 + 221*x^2 + 1201*x - 4938, -75*x^4 + 4*x^3 + 323*x^ 2 + 394*x - 868] -425: [-6*x^4 - 12*x^3 - 21*x^2 - 40*x - 94] -424: [-453*x^4 - 931*x^3 - 1907*x^2 - 3921*x - 8108] -419: [-560*x^4 - 1235*x^3 - 2463*x^2 - 4622*x - 9283] -417: [35136*x^4 + 13626*x^3 - 131611*x^2 - 225241*x + 271295] -416: [-12*x^3 + 40*x^2 - 82*x + 104, x^3 + x^2 - 3*x - 7] -415: [-7002*x^4 + 19830*x^3 + 54916*x^2 - 14183*x - 250846] -412: [-533623*x^4 - 713164*x^3 + 4637959*x^2 - 12427717*x + 21740721] -405: [-1011048403*x^4 + 1415314931*x^3 - 428988586*x^2 - 4570622078*x + 170 45167535] -403: [-78*x^4 - 316*x^3 + 1381*x^2 - 3266*x + 5016] -402: [233347*x^4 + 322792*x^3 - 588962*x^2 - 2139460*x - 270287] -400: [14121*x^4 + 42463*x^3 - 5833*x^2 - 187441*x - 213811, 485552*x^4 - 40 941*x^3 - 2110863*x^2 - 2513370*x + 5748258] -398: [441717*x^4 + 4114047*x^3 - 15578087*x^2 + 34456844*x - 48751711] -394: [-679*x^4 - 1411*x^3 - 2866*x^2 - 5796*x - 11966] -392: [-6*x^4 + 15*x^3 + 43*x^2 - 12*x - 204] -386: [-730*x^4 - 1503*x^3 - 3089*x^2 - 6353*x - 13095] -382: [-51*x^4 + 127*x^3 - 207*x^2 + 151*x + 374, -294*x^4 + 873*x^3 - 1662* x^2 + 1836*x + 929, 289473*x^4 - 50508*x^3 - 1294621*x^2 - 1439915*x + 36421 73] -381: [-57727*x^4 - 148801*x^3 - 285231*x^2 - 433426*x - 786240] -380: [1075950*x^4 - 3190519*x^3 + 6067791*x^2 - 6689147*x - 3438103] -373: [7*x^4 + 5*x^3 - 47*x^2 + 134*x - 250] -372: [151*x^4 - 1096*x^3 - 2144*x^2 + 1693*x + 10780, -88*x^4 - 81*x^3 + 26 7*x^2 + 677*x - 283, 779081*x^4 - 5131030*x^3 + 13790905*x^2 - 24191847*x + 22130971, -52905*x^4 - 2341*x^3 + 232072*x^2 - 763203*x + 1558749] -371: [34641*x^4 - 160448*x^3 - 351019*x^2 + 233495*x + 1785138] -370: [718442*x^4 - 3908961*x^3 + 9976752*x^2 - 16665899*x + 13227796] -365: [-119204*x^4 + 250756*x^3 - 330045*x^2 + 36518*x + 1277460] -364: [155*x^4 + 3056*x^3 + 3149*x^2 - 9118*x - 25302] -361: [112*x^4 - 244*x^3 + 335*x^2 - 88*x - 1140] -360: [360934*x^4 - 4627403*x^3 + 13885713*x^2 - 26642651*x + 29893695] -359: [-3*x^3 + 10*x^2 - 21*x + 27] -358: [-67*x^4 - 301*x^3 - 99*x^2 + 1150*x + 1883] -355: [-119*x^4 - 176*x^3 - 403*x^2 - 1174*x - 2683, -x^4 - 2*x^3 - 4*x^2 - 9*x - 19, 20559*x^4 - 26813*x^3 + 2172*x^2 + 106429*x - 363766] -354: [-x^4 - x^3 + 3*x^2 + 8*x - 3] -350: [435*x^4 - 622*x^3 + 228*x^2 + 1877*x - 7220] -349: [94370*x^4 + 184667*x^3 - 165066*x^2 - 992882*x - 563692] -348: [-2750*x^4 - 1189*x^3 + 10123*x^2 + 17877*x - 20257] -347: [-393095*x^4 + 806794*x^3 - 1021365*x^2 - 17551*x + 4388208] -345: [-x^2 + 4] -343: [-19831*x^4 + 47808*x^3 + 135700*x^2 - 48936*x - 676534] -342: [131*x^4 - 487*x^3 + 1066*x^2 - 1489*x + 437] -340: [461*x^4 + 5016*x^3 + 4154*x^2 - 16543*x - 39824] -338: [139953*x^4 + 382867*x^3 - 110583*x^2 - 1773000*x - 1806375] -337: [-31398*x^4 + 57827*x^3 - 59544*x^2 - 46773*x + 408237] -333: [36*x^4 - 523*x^3 + 1589*x^2 - 3078*x + 3515] -332: [34628262*x^4 - 27740099*x^3 - 54381419*x^2 + 298761718*x - 764765542] -327: [-1312*x^4 - 2690*x^3 - 5512*x^2 - 11363*x - 23526] -326: [-213271*x^4 - 448404*x^3 - 949328*x^2 - 1948400*x - 3893091] -325: [-x^3 - 2*x^2 - 14] -324: [-59*x^4 - 559*x^3 + 2112*x^2 - 4667*x + 6593] -323: [402698*x^4 - 158391*x^3 - 1908700*x^2 - 1757439*x + 5854795] -321: [-4360*x^4 - 9021*x^3 - 18634*x^2 - 38256*x - 78370] -320: [715016*x^4 + 1436884*x^3 - 7817922*x^2 + 19953504*x - 33331798, 10818 *x^4 - 18021*x^3 + 14176*x^2 + 29168*x - 157265] -317: [-26*x^4 + 70*x^3 - 123*x^2 + 113*x + 145] -315: [-15*x^3 + 50*x^2 - 103*x + 131] -314: [-20*x^4 - 42*x^3 - 86*x^2 - 173*x - 353] -313: [11471*x^4 - 91948*x^3 - 165652*x^2 + 178948*x + 929842] -310: [-20259*x^4 - 49809*x^3 - 229335*x^2 - 599186*x - 857837] -306: [72981*x^4 - 634070*x^3 - 1116239*x^2 + 1267500*x + 6344734] -304: [-19*x^4 + 243*x^3 - 731*x^2 + 1401*x - 1577, 62*x^4 - 259*x^3 + 600*x ^2 - 901*x + 458] -296: [2*x^4 - 261*x^3 + 861*x^2 - 1762*x + 2220] -293: [173123*x^4 - 1161964*x^3 + 3137080*x^2 - 5525136*x + 5107878] -292: [-x^4 - 2*x^3 - 4*x^2 - 9*x - 16] -291: [68488791*x^4 - 28662621*x^3 - 194848612*x^2 + 770626148*x - 174127494 7] -289: [-42*x^4 - 68*x^3 - 84*x^2 - 180*x - 617] -288: [190*x^4 + 72*x^3 - 1046*x^2 + 3178*x - 6156, -58*x^4 - 263*x^3 + 1122 *x^2 - 2623*x + 3982] -284: [93394*x^4 - 60075*x^3 - 478379*x^2 - 366460*x + 1536088, 157*x^4 - 58 *x^3 - 791*x^2 - 867*x + 2031, -x^2 - 3*x - 4] -282: [-196079*x^4 - 9567*x^3 + 816242*x^2 + 1073455*x - 2106085] -281: [11*x^4 - 26*x^3 + 40*x^2 - 23*x - 93, -77986*x^4 - 198610*x^3 - 51456 6*x^2 - 1032612*x - 1644077, 46143*x^4 - 67240*x^3 + 28396*x^2 + 190443*x - 754819] -280: [-x - 3] -279: [1826756*x^4 - 4986049*x^3 + 8866643*x^2 - 8401714*x - 9597647] -276: [-581*x^4 - 370*x^3 + 1992*x^2 + 4103*x - 3224] -274: [-x^4 - 2*x^3 - 4*x^2 - 9*x - 18] -272: [329717*x^4 + 475679*x^3 - 792461*x^2 - 3024939*x - 489939, 19260*x^4 - 3158851*x^3 + 10441779*x^2 - 21394937*x + 27010829] -269: [-x^3 - 2*x^2 + 3*x + 11] -267: [8229*x^4 - 28696*x^3 + 60714*x^2 - 80616*x + 11188] -266: [15*x^4 - 5*x^3 - 70*x^2 - 68*x + 210] -265: [-279*x^4 - 1656*x^3 - 925*x^2 + 5842*x + 11353] -260: [6*x^4 + 16*x^3 - 23*x^2 - 134*x - 149] -259: [9*x^4 - 14*x^3 - 56*x^2 - 12*x + 222] -258: [x^4 - 3*x^3 - 8*x^2 + 2*x + 38] -256: [-209*x^4 + 171*x^3 + 315*x^2 - 1777*x + 4579, 120*x^4 + 4*x^3 - 522*x ^2 + 1722*x - 3524, x^4 - 2*x^3 + 2*x^2 - 9] -252: [3*x^4 - 23*x^3 - 42*x^2 + 44*x + 234] -250: [-95029*x^4 + 123210*x^3 - 7619*x^2 - 496926*x + 1687762] -248: [5798*x^4 - 3231*x^3 - 13815*x^2 + 59720*x - 140388] -247: [1023*x^4 - 3286*x^3 - 8521*x^2 + 3081*x + 40030] -245: [-284*x^4 - 92*x^3 - 909*x^2 - 4876*x - 10812] -243: [-3] -239: [6315*x^4 - 83245*x^3 - 134364*x^2 + 178484*x + 789649] -238: [-x^4 - 10*x^3 + 37*x^2 - 82*x + 114] -237: [-x^4 - 2*x^3 - 4*x^2 - 8*x - 18] -234: [-700*x^4 - 3609*x^3 - 1626*x^2 + 13228*x + 23721] -233: [-170*x^4 + 349*x^3 - 442*x^2 - 7*x + 1897] -227: [x^4 + x^3 - 3*x^2 - 8*x + 2] -226: [-2057*x^4 - 4233*x^3 - 8717*x^2 - 17959*x - 36984] -225: [-287*x^4 + 3825*x^3 - 11526*x^2 + 22183*x - 25040] -224: [12*x^4 + 18*x^3 - 28*x^2 - 112*x - 24, 209*x^4 - 305*x^3 - 1277*x^2 - 338*x + 4971] -223: [-x^3 + x^2 - 4*x - 1] -221: [-2*x^4 - 4*x^3 - 8*x^2 - 17*x - 36] -217: [3*x^4 - 10*x^3 + 20*x^2 - 24*x - 2] -213: [-15*x^4 - 40*x^3 - 116*x^2 - 243*x - 363, -5266075*x^4 + 2073982*x^3 + 15414497*x^2 - 60143957*x + 135019482] -212: [-115365677*x^4 + 45854629*x^3 + 336294021*x^2 - 1314718510*x + 295425 8329] -208: [1723*x^4 + 323*x^3 - 6895*x^2 - 10147*x + 16309, 4616*x^4 - 77366*x^3 - 118173*x^2 + 177269*x + 725858] -206: [x - 3] -201: [-x^4 + 5*x^3 - 17*x^2 + 26*x - 34] -200: [-9*x^4 + 15*x^3 - 12*x^2 - 24*x + 130] -199: [-2*x^4 - 4*x^3 - 7*x^2 - 19*x - 29] -197: [22383064*x^4 - 43634035*x^3 + 50477245*x^2 + 16811671*x - 269988108] -196: [-6793545*x^4 + 10693841*x^3 - 6826578*x^2 - 22590870*x + 104198448] -193: [151377130*x^4 - 431708160*x^3 + 796483374*x^2 - 823328390*x - 6335835 09] -191: [-99*x^4 - 176*x^3 - 284*x^2 - 603*x - 1597, -55*x^4 - 112*x^3 + 90*x^ 2 + 588*x + 364, -3*x^4 + 10*x^3 - 22*x^2 + 28*x - 6] -190: [-x^2 + x + 2] -186: [11602*x^4 - 9070*x^3 - 18967*x^2 + 101636*x - 258187, 142431*x^4 + 48 0237*x^3 - 2203655*x^2 + 5305471*x - 8333030, -4*x^4 - 8*x^3 - 18*x^2 - 33*x - 75, x^4 - 2*x^3 + 4*x^2 - 8*x - 1] -185: [-x^2 + 2*x] -182: [-5804*x^4 + 5839*x^3 + 5152*x^2 - 41916*x + 117799] -180: [-x^2 + 3*x - 2] -179: [5089960*x^4 - 2068704*x^3 - 14685499*x^2 + 57692992*x - 129944660] -177: [82854*x^4 + 117450*x^3 - 202163*x^2 - 755931*x - 106537] -175: [-72*x^4 - 148*x^3 - 316*x^2 - 666*x - 1343] -174: [-41*x^4 - 8383*x^3 + 28101*x^2 - 58079*x + 74360] -171: [-802*x^4 - 1651*x^3 - 3405*x^2 - 7019*x - 14438] -170: [-6*x^4 + 2608*x^3 - 8663*x^2 + 17804*x - 22589] -169: [-4*x^4 + 15*x^2 - 54*x + 108] -166: [-3*x^4 + 4*x^3 - 17*x + 54] -163: [2245*x^4 - 3153*x^3 + 987*x^2 + 10078*x - 37758] -162: [-277*x^4 - 572*x^3 - 1182*x^2 - 2432*x - 4987] -160: [-2*x + 4, -5*x^3 - 7*x^2 + 11*x + 41] -157: [-241448*x^4 - 417679*x^3 - 864708*x^2 - 2123175*x - 4787585] -155: [-772*x^4 + 2268*x^3 - 4283*x^2 + 4654*x + 2652] -153: [59*x^4 - 112*x^3 + 123*x^2 + 65*x - 738] -152: [-439*x^4 - 73*x^3 + 1768*x^2 + 2559*x - 4239] -148: [-297*x^4 + 224*x^3 + 1544*x^2 + 1015*x - 5254] -146: [-12135*x^4 - 22239*x^3 - 42377*x^2 - 94551*x - 218424] -144: [-525*x^4 - 1079*x^3 - 2223*x^2 - 4587*x - 9451, -155*x^4 + 521*x^3 + 1320*x^2 - 529*x - 6269] -142: [3*x^4 + 5*x^3 - 32*x^2 + 80*x - 142, 42124*x^4 - 125551*x^3 + 239691* x^2 - 266277*x - 129013, -13516*x^4 - 35437*x^3 + 1336*x^2 + 129548*x + 1131 15] -141: [6*x^4 - 5*x^3 - 10*x^2 + 52*x - 136] -140: [-391*x^4 - 16914*x^3 - 23679*x^2 + 33718*x + 127118] -138: [-346952*x^4 + 739554*x^3 - 992969*x^2 + 172892*x + 3633389] -137: [-10436*x^4 - 28118*x^3 - 58568*x^2 - 93336*x - 154633] -136: [-x^2 + x - 4] -133: [11850914*x^4 - 39486071*x^3 + 81306239*x^2 - 103476243*x + 50856] -130: [148905438*x^4 - 497156819*x^3 + 1024997560*x^2 - 1307154759*x + 95299 62] -129: [-121239*x^4 + 197007*x^3 + 764634*x^2 + 137825*x - 3066062] -128: [-284*x^4 - 594*x^3 + 448*x^2 + 3088*x + 2030, -6844*x^4 + 4689*x^3 + 34974*x^2 + 24615*x - 116962] -126: [-579103*x^4 - 50757882*x^3 + 171550192*x^2 - 356332674*x + 459859773] -125: [-16*x^4 - 33*x^3 - 68*x^2 - 140*x - 288] -124: [-63*x^4 - 130*x^3 - 268*x^2 - 551*x - 1132] -119: [-378*x^4 - 819*x^3 - 1878*x^2 - 3938*x - 7386] -117: [16530*x^4 - 73563*x^3 + 174995*x^2 - 271134*x + 161425] -113: [101777454*x^4 - 158642204*x^3 + 97050316*x^2 + 349196731*x - 15747298 66] -112: [12430017*x^4 + 11271811*x^3 - 90243953*x^2 + 252856431*x - 459808917, 137153*x^4 - 248761*x^3 + 247310*x^2 + 230649*x - 1816775] -106: [11*x^4 - 11*x^3 - 10*x^2 + 80*x - 224] -104: [128*x^4 - 165*x^3 + 7*x^2 + 676*x - 2282] -103: [5488*x^4 - 723*x^3 - 24894*x^2 - 30073*x + 64255] -100: [-182*x^4 - 416*x^3 - 585*x^2 - 684*x - 1897] -98: [-2*x^3 - x^2 - 4*x - 15] -95: [-6855*x^4 + 14582*x^3 + 47479*x^2 - 1679*x - 203984] -93: [-36*x^4 - 74*x^3 - 152*x^2 - 313*x - 646, -x^4 - 2*x^3 - 4*x^2 - 9*x - 17, 814*x^4 - 2981*x^3 - 7244*x^2 + 3419*x + 35059, -20965*x^4 - 37774*x^3 + 40807*x^2 + 212056*x + 96849] -91: [-27*x^4 - 56*x^3 - 116*x^2 - 238*x - 486] -90: [2422*x^4 + 19015*x^3 + 13882*x^2 - 63040*x - 139265] -87: [-7*x^4 - 14*x^3 - 30*x^2 - 65*x - 133] -85: [2*x^4 + 10*x^3 + 4*x^2 - 37*x - 64] -83: [-2588*x^4 - 12178*x^3 - 4526*x^2 + 45864*x + 77545] -81: [266742807*x^4 - 477562789*x^3 + 460189353*x^2 + 491390120*x - 35878418 38] -80: [-9277*x^4 - 4433*x^3 + 33597*x^2 + 61361*x - 64719, -56126*x^4 + 37330 0*x^3 + 705659*x^2 - 699545*x - 3912460] -76: [-170837*x^4 + 734276*x^3 - 1721967*x^2 + 2623857*x - 1441433] -74: [5278*x^4 + 728998*x^3 - 2450965*x^2 + 5074822*x - 6516255] -73: [25820*x^4 - 67564*x^3 + 115628*x^2 - 98789*x - 161060] -72: [181393*x^4 + 723720*x^3 - 3179963*x^2 + 7525787*x - 11591077] -71: [-1991*x^4 - 4101*x^3 - 8378*x^2 - 17159*x - 35492, -17*x^4 - 35*x^3 - 72*x^2 - 148*x - 305, -5556*x^4 + 9447*x^3 - 7919*x^2 - 13666*x + 79097] -70: [2020*x^4 + 20331*x^3 - 76294*x^2 + 167980*x - 236187] -69: [-x - 2] -68: [-1758*x^4 - 3055*x^3 - 1094*x^2 + 1966*x - 12611] -65: [-6*x^4 + 32*x^3 - 81*x^2 + 134*x - 104] -64: [-352230*x^4 + 10556*x^3 + 1457996*x^2 - 4901930*x + 10149644, -2661*x^ 4 + 5496*x^3 - 7029*x^2 + 118*x + 29404] -63: [x^4 + 2*x^3 - 11*x^2 + 28*x - 47] -62: [-739233*x^4 - 1498725*x^3 - 3047259*x^2 - 6323853*x - 13246892] -56: [-x^4 - 2*x^3 - 4*x^2 - 8*x - 17] -53: [325*x^4 + 371*x^3 - 914*x^2 - 2753*x + 336] -52: [-57*x^4 - 108*x^3 - 200*x^2 - 423*x - 980] -50: [25730*x^4 - 43569*x^3 + 36072*x^2 + 64525*x - 367876] -49: [-5896*x^4 - 12076*x^3 - 24244*x^2 - 49397*x - 103670] -45: [-154*x^4 - 595*x^3 + 2635*x^2 - 6256*x + 9671] -40: [-118*x^4 - 265*x^3 + 1383*x^2 - 3484*x + 5744] -38: [-x - 1] -37: [-x] -36: [-x + 1] -35: [-3*x^4 - 32*x^3 - 28*x^2 + 100*x + 246] -34: [-173*x^4 - 352*x^3 + 1904*x^2 - 4855*x + 8094] -32: [-2, -x^4 - 2*x^3 - 9*x^2 - 25*x - 39] -31: [124*x^4 - 524*x^3 + 1220*x^2 - 1843*x + 968] -28: [-8346*x^4 - 17083*x^3 - 51080*x^2 - 125839*x - 217960] -26: [-19911372*x^4 + 109082694*x^3 - 278991431*x^2 + 467014698*x - 37312536 3] -25: [-x^2 + 4*x - 4] -20: [-13*x^4 + 818*x^3 + 1096*x^2 - 2073*x - 7284] -19: [-2090*x^4 - 11035*x^3 - 7488*x^2 + 32503*x + 63327] -18: [-3789*x^4 - 5156*x^3 + 8703*x^2 + 31288*x - 464] -17: [-2*x^4 - 2*x^3 + 6*x^2 + 16*x - 5] -16: [1699*x^4 - 5879*x^3 - 16191*x^2 + 1215*x + 63791, -80106*x^4 - 216338* x^3 - 59376*x^2 + 586907*x + 474269] -14: [-2087*x^4 - 2154*x^3 + 16023*x^2 - 44248*x + 79484] -13: [-6*x^3 + 20*x^2 - 41*x + 52] -10: [357508*x^4 + 718442*x^3 - 3908961*x^2 + 9976752*x - 16665899] -9: [95*x^4 + 36*x^3 - 523*x^2 + 1589*x - 3078] -8: [60*x^4 + 2*x^3 - 261*x^2 + 861*x - 1762] -7: [6*x^4 + 9*x^3 - 14*x^2 - 56*x - 12] -5: [-x + 2] -4: [-142*x^4 - 297*x^3 + 224*x^2 + 1544*x + 1015] -2: [-176115*x^4 + 5278*x^3 + 728998*x^2 - 2450965*x + 5074822] -1: [-1] 0: [0] 1: [1] 2: [176115*x^4 - 5278*x^3 - 728998*x^2 + 2450965*x - 5074822] 4: [142*x^4 + 297*x^3 - 224*x^2 - 1544*x - 1015] 5: [x - 2] 7: [-6*x^4 - 9*x^3 + 14*x^2 + 56*x + 12] 8: [-60*x^4 - 2*x^3 + 261*x^2 - 861*x + 1762] 9: [-95*x^4 - 36*x^3 + 523*x^2 - 1589*x + 3078] 10: [-357508*x^4 - 718442*x^3 + 3908961*x^2 - 9976752*x + 16665899] 13: [6*x^3 - 20*x^2 + 41*x - 52] 14: [2087*x^4 + 2154*x^3 - 16023*x^2 + 44248*x - 79484] 16: [-1699*x^4 + 5879*x^3 + 16191*x^2 - 1215*x - 63791, 80106*x^4 + 216338*x ^3 + 59376*x^2 - 586907*x - 474269] 17: [2*x^4 + 2*x^3 - 6*x^2 - 16*x + 5] 18: [3789*x^4 + 5156*x^3 - 8703*x^2 - 31288*x + 464] 19: [2090*x^4 + 11035*x^3 + 7488*x^2 - 32503*x - 63327] 20: [13*x^4 - 818*x^3 - 1096*x^2 + 2073*x + 7284] 25: [x^2 - 4*x + 4] 26: [19911372*x^4 - 109082694*x^3 + 278991431*x^2 - 467014698*x + 373125363] 28: [8346*x^4 + 17083*x^3 + 51080*x^2 + 125839*x + 217960] 31: [-124*x^4 + 524*x^3 - 1220*x^2 + 1843*x - 968] 32: [2, x^4 + 2*x^3 + 9*x^2 + 25*x + 39] 34: [173*x^4 + 352*x^3 - 1904*x^2 + 4855*x - 8094] 35: [3*x^4 + 32*x^3 + 28*x^2 - 100*x - 246] 36: [x - 1] 37: [x] 38: [x + 1] 40: [118*x^4 + 265*x^3 - 1383*x^2 + 3484*x - 5744] 45: [154*x^4 + 595*x^3 - 2635*x^2 + 6256*x - 9671] 49: [5896*x^4 + 12076*x^3 + 24244*x^2 + 49397*x + 103670] 50: [-25730*x^4 + 43569*x^3 - 36072*x^2 - 64525*x + 367876] 52: [57*x^4 + 108*x^3 + 200*x^2 + 423*x + 980] 53: [-325*x^4 - 371*x^3 + 914*x^2 + 2753*x - 336] 56: [x^4 + 2*x^3 + 4*x^2 + 8*x + 17] 62: [739233*x^4 + 1498725*x^3 + 3047259*x^2 + 6323853*x + 13246892] 63: [-x^4 - 2*x^3 + 11*x^2 - 28*x + 47] 64: [352230*x^4 - 10556*x^3 - 1457996*x^2 + 4901930*x - 10149644, 2661*x^4 - 5496*x^3 + 7029*x^2 - 118*x - 29404] 65: [6*x^4 - 32*x^3 + 81*x^2 - 134*x + 104] 68: [1758*x^4 + 3055*x^3 + 1094*x^2 - 1966*x + 12611] 69: [x + 2] 70: [-2020*x^4 - 20331*x^3 + 76294*x^2 - 167980*x + 236187] 71: [1991*x^4 + 4101*x^3 + 8378*x^2 + 17159*x + 35492, 17*x^4 + 35*x^3 + 72* x^2 + 148*x + 305, 5556*x^4 - 9447*x^3 + 7919*x^2 + 13666*x - 79097] 72: [-181393*x^4 - 723720*x^3 + 3179963*x^2 - 7525787*x + 11591077] 73: [-25820*x^4 + 67564*x^3 - 115628*x^2 + 98789*x + 161060] 74: [-5278*x^4 - 728998*x^3 + 2450965*x^2 - 5074822*x + 6516255] 76: [170837*x^4 - 734276*x^3 + 1721967*x^2 - 2623857*x + 1441433] 80: [9277*x^4 + 4433*x^3 - 33597*x^2 - 61361*x + 64719, 56126*x^4 - 373300*x ^3 - 705659*x^2 + 699545*x + 3912460] 81: [-266742807*x^4 + 477562789*x^3 - 460189353*x^2 - 491390120*x + 35878418 38] 83: [2588*x^4 + 12178*x^3 + 4526*x^2 - 45864*x - 77545] 85: [-2*x^4 - 10*x^3 - 4*x^2 + 37*x + 64] 87: [7*x^4 + 14*x^3 + 30*x^2 + 65*x + 133] 90: [-2422*x^4 - 19015*x^3 - 13882*x^2 + 63040*x + 139265] 91: [27*x^4 + 56*x^3 + 116*x^2 + 238*x + 486] 93: [36*x^4 + 74*x^3 + 152*x^2 + 313*x + 646, x^4 + 2*x^3 + 4*x^2 + 9*x + 17 , -814*x^4 + 2981*x^3 + 7244*x^2 - 3419*x - 35059, 20965*x^4 + 37774*x^3 - 4 0807*x^2 - 212056*x - 96849] 95: [6855*x^4 - 14582*x^3 - 47479*x^2 + 1679*x + 203984] 98: [2*x^3 + x^2 + 4*x + 15] 100: [182*x^4 + 416*x^3 + 585*x^2 + 684*x + 1897] 103: [-5488*x^4 + 723*x^3 + 24894*x^2 + 30073*x - 64255] 104: [-128*x^4 + 165*x^3 - 7*x^2 - 676*x + 2282] 106: [-11*x^4 + 11*x^3 + 10*x^2 - 80*x + 224] 112: [-12430017*x^4 - 11271811*x^3 + 90243953*x^2 - 252856431*x + 459808917, -137153*x^4 + 248761*x^3 - 247310*x^2 - 230649*x + 1816775] 113: [-101777454*x^4 + 158642204*x^3 - 97050316*x^2 - 349196731*x + 15747298 66] 117: [-16530*x^4 + 73563*x^3 - 174995*x^2 + 271134*x - 161425] 119: [378*x^4 + 819*x^3 + 1878*x^2 + 3938*x + 7386] 124: [63*x^4 + 130*x^3 + 268*x^2 + 551*x + 1132] 125: [16*x^4 + 33*x^3 + 68*x^2 + 140*x + 288] 126: [579103*x^4 + 50757882*x^3 - 171550192*x^2 + 356332674*x - 459859773] 128: [284*x^4 + 594*x^3 - 448*x^2 - 3088*x - 2030, 6844*x^4 - 4689*x^3 - 349 74*x^2 - 24615*x + 116962] 129: [121239*x^4 - 197007*x^3 - 764634*x^2 - 137825*x + 3066062] 130: [-148905438*x^4 + 497156819*x^3 - 1024997560*x^2 + 1307154759*x - 95299 62] 133: [-11850914*x^4 + 39486071*x^3 - 81306239*x^2 + 103476243*x - 50856] 136: [x^2 - x + 4] 137: [10436*x^4 + 28118*x^3 + 58568*x^2 + 93336*x + 154633] 138: [346952*x^4 - 739554*x^3 + 992969*x^2 - 172892*x - 3633389] 140: [391*x^4 + 16914*x^3 + 23679*x^2 - 33718*x - 127118] 141: [-6*x^4 + 5*x^3 + 10*x^2 - 52*x + 136] 142: [-3*x^4 - 5*x^3 + 32*x^2 - 80*x + 142, -42124*x^4 + 125551*x^3 - 239691 *x^2 + 266277*x + 129013, 13516*x^4 + 35437*x^3 - 1336*x^2 - 129548*x - 1131 15] 144: [525*x^4 + 1079*x^3 + 2223*x^2 + 4587*x + 9451, 155*x^4 - 521*x^3 - 132 0*x^2 + 529*x + 6269] 146: [12135*x^4 + 22239*x^3 + 42377*x^2 + 94551*x + 218424] 148: [297*x^4 - 224*x^3 - 1544*x^2 - 1015*x + 5254] 152: [439*x^4 + 73*x^3 - 1768*x^2 - 2559*x + 4239] 153: [-59*x^4 + 112*x^3 - 123*x^2 - 65*x + 738] 155: [772*x^4 - 2268*x^3 + 4283*x^2 - 4654*x - 2652] 157: [241448*x^4 + 417679*x^3 + 864708*x^2 + 2123175*x + 4787585] 160: [2*x - 4, 5*x^3 + 7*x^2 - 11*x - 41] 162: [277*x^4 + 572*x^3 + 1182*x^2 + 2432*x + 4987] 163: [-2245*x^4 + 3153*x^3 - 987*x^2 - 10078*x + 37758] 166: [3*x^4 - 4*x^3 + 17*x - 54] 169: [4*x^4 - 15*x^2 + 54*x - 108] 170: [6*x^4 - 2608*x^3 + 8663*x^2 - 17804*x + 22589] 171: [802*x^4 + 1651*x^3 + 3405*x^2 + 7019*x + 14438] 174: [41*x^4 + 8383*x^3 - 28101*x^2 + 58079*x - 74360] 175: [72*x^4 + 148*x^3 + 316*x^2 + 666*x + 1343] 177: [-82854*x^4 - 117450*x^3 + 202163*x^2 + 755931*x + 106537] 179: [-5089960*x^4 + 2068704*x^3 + 14685499*x^2 - 57692992*x + 129944660] 180: [x^2 - 3*x + 2] 182: [5804*x^4 - 5839*x^3 - 5152*x^2 + 41916*x - 117799] 185: [x^2 - 2*x] 186: [-11602*x^4 + 9070*x^3 + 18967*x^2 - 101636*x + 258187, -142431*x^4 - 4 80237*x^3 + 2203655*x^2 - 5305471*x + 8333030, 4*x^4 + 8*x^3 + 18*x^2 + 33*x + 75, -x^4 + 2*x^3 - 4*x^2 + 8*x + 1] 190: [x^2 - x - 2] 191: [99*x^4 + 176*x^3 + 284*x^2 + 603*x + 1597, 55*x^4 + 112*x^3 - 90*x^2 - 588*x - 364, 3*x^4 - 10*x^3 + 22*x^2 - 28*x + 6] 193: [-151377130*x^4 + 431708160*x^3 - 796483374*x^2 + 823328390*x + 6335835 09] 196: [6793545*x^4 - 10693841*x^3 + 6826578*x^2 + 22590870*x - 104198448] 197: [-22383064*x^4 + 43634035*x^3 - 50477245*x^2 - 16811671*x + 269988108] 199: [2*x^4 + 4*x^3 + 7*x^2 + 19*x + 29] 200: [9*x^4 - 15*x^3 + 12*x^2 + 24*x - 130] 201: [x^4 - 5*x^3 + 17*x^2 - 26*x + 34] 206: [-x + 3] 208: [-1723*x^4 - 323*x^3 + 6895*x^2 + 10147*x - 16309, -4616*x^4 + 77366*x^ 3 + 118173*x^2 - 177269*x - 725858] 212: [115365677*x^4 - 45854629*x^3 - 336294021*x^2 + 1314718510*x - 29542583 29] 213: [15*x^4 + 40*x^3 + 116*x^2 + 243*x + 363, 5266075*x^4 - 2073982*x^3 - 1 5414497*x^2 + 60143957*x - 135019482] 217: [-3*x^4 + 10*x^3 - 20*x^2 + 24*x + 2] 221: [2*x^4 + 4*x^3 + 8*x^2 + 17*x + 36] 223: [x^3 - x^2 + 4*x + 1] 224: [-12*x^4 - 18*x^3 + 28*x^2 + 112*x + 24, -209*x^4 + 305*x^3 + 1277*x^2 + 338*x - 4971] 225: [287*x^4 - 3825*x^3 + 11526*x^2 - 22183*x + 25040] 226: [2057*x^4 + 4233*x^3 + 8717*x^2 + 17959*x + 36984] 227: [-x^4 - x^3 + 3*x^2 + 8*x - 2] 233: [170*x^4 - 349*x^3 + 442*x^2 + 7*x - 1897] 234: [700*x^4 + 3609*x^3 + 1626*x^2 - 13228*x - 23721] 237: [x^4 + 2*x^3 + 4*x^2 + 8*x + 18] 238: [x^4 + 10*x^3 - 37*x^2 + 82*x - 114] 239: [-6315*x^4 + 83245*x^3 + 134364*x^2 - 178484*x - 789649] 243: [3] 245: [284*x^4 + 92*x^3 + 909*x^2 + 4876*x + 10812] 247: [-1023*x^4 + 3286*x^3 + 8521*x^2 - 3081*x - 40030] 248: [-5798*x^4 + 3231*x^3 + 13815*x^2 - 59720*x + 140388] 250: [95029*x^4 - 123210*x^3 + 7619*x^2 + 496926*x - 1687762] 252: [-3*x^4 + 23*x^3 + 42*x^2 - 44*x - 234] 256: [209*x^4 - 171*x^3 - 315*x^2 + 1777*x - 4579, -120*x^4 - 4*x^3 + 522*x^ 2 - 1722*x + 3524, -x^4 + 2*x^3 - 2*x^2 + 9] 258: [-x^4 + 3*x^3 + 8*x^2 - 2*x - 38] 259: [-9*x^4 + 14*x^3 + 56*x^2 + 12*x - 222] 260: [-6*x^4 - 16*x^3 + 23*x^2 + 134*x + 149] 265: [279*x^4 + 1656*x^3 + 925*x^2 - 5842*x - 11353] 266: [-15*x^4 + 5*x^3 + 70*x^2 + 68*x - 210] 267: [-8229*x^4 + 28696*x^3 - 60714*x^2 + 80616*x - 11188] 269: [x^3 + 2*x^2 - 3*x - 11] 272: [-329717*x^4 - 475679*x^3 + 792461*x^2 + 3024939*x + 489939, -19260*x^4 + 3158851*x^3 - 10441779*x^2 + 21394937*x - 27010829] 274: [x^4 + 2*x^3 + 4*x^2 + 9*x + 18] 276: [581*x^4 + 370*x^3 - 1992*x^2 - 4103*x + 3224] 279: [-1826756*x^4 + 4986049*x^3 - 8866643*x^2 + 8401714*x + 9597647] 280: [x + 3] 281: [-11*x^4 + 26*x^3 - 40*x^2 + 23*x + 93, 77986*x^4 + 198610*x^3 + 514566 *x^2 + 1032612*x + 1644077, -46143*x^4 + 67240*x^3 - 28396*x^2 - 190443*x + 754819] 282: [196079*x^4 + 9567*x^3 - 816242*x^2 - 1073455*x + 2106085] 284: [-93394*x^4 + 60075*x^3 + 478379*x^2 + 366460*x - 1536088, -157*x^4 + 5 8*x^3 + 791*x^2 + 867*x - 2031, x^2 + 3*x + 4] 288: [-190*x^4 - 72*x^3 + 1046*x^2 - 3178*x + 6156, 58*x^4 + 263*x^3 - 1122* x^2 + 2623*x - 3982] 289: [42*x^4 + 68*x^3 + 84*x^2 + 180*x + 617] 291: [-68488791*x^4 + 28662621*x^3 + 194848612*x^2 - 770626148*x + 174127494 7] 292: [x^4 + 2*x^3 + 4*x^2 + 9*x + 16] 293: [-173123*x^4 + 1161964*x^3 - 3137080*x^2 + 5525136*x - 5107878] 296: [-2*x^4 + 261*x^3 - 861*x^2 + 1762*x - 2220] 304: [19*x^4 - 243*x^3 + 731*x^2 - 1401*x + 1577, -62*x^4 + 259*x^3 - 600*x^ 2 + 901*x - 458] 306: [-72981*x^4 + 634070*x^3 + 1116239*x^2 - 1267500*x - 6344734] 310: [20259*x^4 + 49809*x^3 + 229335*x^2 + 599186*x + 857837] 313: [-11471*x^4 + 91948*x^3 + 165652*x^2 - 178948*x - 929842] 314: [20*x^4 + 42*x^3 + 86*x^2 + 173*x + 353] 315: [15*x^3 - 50*x^2 + 103*x - 131] 317: [26*x^4 - 70*x^3 + 123*x^2 - 113*x - 145] 320: [-715016*x^4 - 1436884*x^3 + 7817922*x^2 - 19953504*x + 33331798, -1081 8*x^4 + 18021*x^3 - 14176*x^2 - 29168*x + 157265] 321: [4360*x^4 + 9021*x^3 + 18634*x^2 + 38256*x + 78370] 323: [-402698*x^4 + 158391*x^3 + 1908700*x^2 + 1757439*x - 5854795] 324: [59*x^4 + 559*x^3 - 2112*x^2 + 4667*x - 6593] 325: [x^3 + 2*x^2 + 14] 326: [213271*x^4 + 448404*x^3 + 949328*x^2 + 1948400*x + 3893091] 327: [1312*x^4 + 2690*x^3 + 5512*x^2 + 11363*x + 23526] 332: [-34628262*x^4 + 27740099*x^3 + 54381419*x^2 - 298761718*x + 764765542] 333: [-36*x^4 + 523*x^3 - 1589*x^2 + 3078*x - 3515] 337: [31398*x^4 - 57827*x^3 + 59544*x^2 + 46773*x - 408237] 338: [-139953*x^4 - 382867*x^3 + 110583*x^2 + 1773000*x + 1806375] 340: [-461*x^4 - 5016*x^3 - 4154*x^2 + 16543*x + 39824] 342: [-131*x^4 + 487*x^3 - 1066*x^2 + 1489*x - 437] 343: [19831*x^4 - 47808*x^3 - 135700*x^2 + 48936*x + 676534] 345: [x^2 - 4] 347: [393095*x^4 - 806794*x^3 + 1021365*x^2 + 17551*x - 4388208] 348: [2750*x^4 + 1189*x^3 - 10123*x^2 - 17877*x + 20257] 349: [-94370*x^4 - 184667*x^3 + 165066*x^2 + 992882*x + 563692] 350: [-435*x^4 + 622*x^3 - 228*x^2 - 1877*x + 7220] 354: [x^4 + x^3 - 3*x^2 - 8*x + 3] 355: [119*x^4 + 176*x^3 + 403*x^2 + 1174*x + 2683, x^4 + 2*x^3 + 4*x^2 + 9*x + 19, -20559*x^4 + 26813*x^3 - 2172*x^2 - 106429*x + 363766] 358: [67*x^4 + 301*x^3 + 99*x^2 - 1150*x - 1883] 359: [3*x^3 - 10*x^2 + 21*x - 27] 360: [-360934*x^4 + 4627403*x^3 - 13885713*x^2 + 26642651*x - 29893695] 361: [-112*x^4 + 244*x^3 - 335*x^2 + 88*x + 1140] 364: [-155*x^4 - 3056*x^3 - 3149*x^2 + 9118*x + 25302] 365: [119204*x^4 - 250756*x^3 + 330045*x^2 - 36518*x - 1277460] 370: [-718442*x^4 + 3908961*x^3 - 9976752*x^2 + 16665899*x - 13227796] 371: [-34641*x^4 + 160448*x^3 + 351019*x^2 - 233495*x - 1785138] 372: [-151*x^4 + 1096*x^3 + 2144*x^2 - 1693*x - 10780, 88*x^4 + 81*x^3 - 267 *x^2 - 677*x + 283, -779081*x^4 + 5131030*x^3 - 13790905*x^2 + 24191847*x - 22130971, 52905*x^4 + 2341*x^3 - 232072*x^2 + 763203*x - 1558749] 373: [-7*x^4 - 5*x^3 + 47*x^2 - 134*x + 250] 380: [-1075950*x^4 + 3190519*x^3 - 6067791*x^2 + 6689147*x + 3438103] 381: [57727*x^4 + 148801*x^3 + 285231*x^2 + 433426*x + 786240] 382: [51*x^4 - 127*x^3 + 207*x^2 - 151*x - 374, 294*x^4 - 873*x^3 + 1662*x^2 - 1836*x - 929, -289473*x^4 + 50508*x^3 + 1294621*x^2 + 1439915*x - 3642173 ] 386: [730*x^4 + 1503*x^3 + 3089*x^2 + 6353*x + 13095] 392: [6*x^4 - 15*x^3 - 43*x^2 + 12*x + 204] 394: [679*x^4 + 1411*x^3 + 2866*x^2 + 5796*x + 11966] 398: [-441717*x^4 - 4114047*x^3 + 15578087*x^2 - 34456844*x + 48751711] 400: [-14121*x^4 - 42463*x^3 + 5833*x^2 + 187441*x + 213811, -485552*x^4 + 4 0941*x^3 + 2110863*x^2 + 2513370*x - 5748258] 402: [-233347*x^4 - 322792*x^3 + 588962*x^2 + 2139460*x + 270287] 403: [78*x^4 + 316*x^3 - 1381*x^2 + 3266*x - 5016] 405: [1011048403*x^4 - 1415314931*x^3 + 428988586*x^2 + 4570622078*x - 17045 167535] 412: [533623*x^4 + 713164*x^3 - 4637959*x^2 + 12427717*x - 21740721] 415: [7002*x^4 - 19830*x^3 - 54916*x^2 + 14183*x + 250846] 416: [12*x^3 - 40*x^2 + 82*x - 104, -x^3 - x^2 + 3*x + 7] 417: [-35136*x^4 - 13626*x^3 + 131611*x^2 + 225241*x - 271295] 419: [560*x^4 + 1235*x^3 + 2463*x^2 + 4622*x + 9283] 424: [453*x^4 + 931*x^3 + 1907*x^2 + 3921*x + 8108] 425: [6*x^4 + 12*x^3 + 21*x^2 + 40*x + 94] 426: [-307*x^4 + 457*x^3 - 221*x^2 - 1201*x + 4938, 75*x^4 - 4*x^3 - 323*x^2 - 394*x + 868] 434: [229020*x^4 - 2937*x^3 - 961070*x^2 + 3214168*x - 6633571] 435: [2*x^3 + 5*x^2 + 3*x - 7] 439: [340*x^4 - 658*x^3 + 751*x^2 + 288*x - 4142] 441: [-x^3 - x^2 + 2*x + 9] 442: [72646*x^4 - 242032*x^3 + 498349*x^2 - 634190*x + 161] 443: [-52874*x^4 - 359697*x^3 - 233432*x^2 + 1228056*x + 2552814] 446: [3334966*x^4 - 10447057*x^3 + 20665939*x^2 - 24559864*x - 5787442] 447: [3023*x^4 - 8573*x^3 - 23724*x^2 + 6154*x + 108401] 448: [4174*x^4 + 4308*x^3 - 32046*x^2 + 88496*x - 158968, 48*x^4 - 86*x^3 + 83*x^2 + 88*x - 645] 450: [-14171*x^4 + 24148*x^3 + 90804*x^2 + 13185*x - 368144] 452: [-17*x^4 + 280*x^3 - 858*x^2 + 1677*x - 1938] 454: [42409*x^4 + 90034*x^3 - 479719*x^2 + 1216471*x - 2018953] 455: [2*x^4 + 4*x^3 + 6*x^2 + 10*x + 27] 457: [-87*x^4 - 185*x^3 + 134*x^2 + 956*x + 651] 461: [-x^4 + 2*x^3 - 3*x^2 + 4*x + 5] 463: [-11*x^4 + 5*x^3 + 30*x^2 - 121*x + 276] 465: [2*x^4 + 4*x^3 + 9*x^2 + 20*x + 40, x^2 - x + 3, 4609*x^4 + 1282*x^3 - 17907*x^2 - 28221*x + 40000, -4156*x^4 - 116355*x^3 - 130442*x^2 + 327263*x + 969403] 466: [1159032*x^4 + 2381161*x^3 + 4715244*x^2 + 9491919*x + 20062122] 468: [6*x^4 - 26*x^3 + 61*x^2 - 93*x + 52] 474: [38962*x^4 + 243483*x^3 - 976308*x^2 + 2220316*x - 3258047] 475: [-28292*x^4 - 18315*x^3 + 96637*x^2 + 200626*x - 154333] 476: [149520*x^4 - 433375*x^3 - 1184038*x^2 + 333085*x + 5448548] 477: [3*x^4 + 6*x^3 + 12*x^2 + 25*x + 53] 478: [-x^3 - x^2 + 3*x + 9] 481: [6*x^4 - 20*x^3 + 41*x^2 - 52*x] 483: [-21*x^4 - 4*x^3 + 84*x^2 + 124*x - 198] 486: [528345*x^4 - 15834*x^3 - 2186994*x^2 + 7352895*x - 15224466] 487: [5668*x^4 - 14258*x^3 + 23472*x^2 - 17752*x - 40361] 490: [2*x^4 - 3*x^3 + 2*x^2 + 7*x - 30] 491: [-1888*x^4 - 8569*x^3 - 2900*x^2 + 32636*x + 53824, -6486*x^4 + 17022*x ^3 - 29212*x^2 + 25158*x + 40023, 1027*x^4 + 866*x^3 - 3228*x^2 - 7730*x + 3 948] 494: [6*x^4 - 14*x^3 + 21*x^2 - 11*x - 52] 496: [33*x^4 - 31*x^3 - 177*x^2 - 89*x + 647, -306*x^4 - 1960*x^3 - 1005*x^2 + 7425*x + 14522] 497: [3457*x^4 - 2824*x^3 - 15097*x^2 - 751*x + 76402, 10*x^4 + 5*x^3 - 9*x^ 2 + 23*x + 182, x^3 - 2*x^2 + 5*x - 3] 499: [2374*x^4 - 1671*x^3 - 4497*x^2 + 22065*x - 54444] 500: [52*x^4 - 247*x^3 - 486*x^2 + 529*x + 2940] ? bnfisintnorm(bnfinit(x^3+5),5) [-x] ? print("Total time spent: ",gettime); Total time spent: 528 pari-2.5.5/src/test/64/ff0000644000175000017500000001652412147140047013431 0ustar billbill *** Warning: new stack size = 50000000 (47.684 Mbytes). ? 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], 0, a/x, 1, a^18 + a^16 + a ^13 + a^12 + a^9 + a^8 + a^7 + a^5 + a^4 + a^2, 1048575, a, [x + (a^18 + a^1 6 + a^13 + a^9 + a^8 + a^7 + a^6 + a^4 + a^2 + a), 1; x + (a^18 + a^16 + a^1 3 + 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, 0, 0, 0, 0, 0, 0], a/ x, (x + a)/(x + 6*a), 2*a^6 + 2*a^5 + 5*a^4 + 3*a^3 + 4*a + 3, 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, 0, 0, 0, 0 , 0, 0], a/x, (x + a)/(x + 4294967290*a), 3219540619*a^2 + 1467235354*a + 23 11182475, 36893488070109691946, a, [x + (1365670490*a^2 + 3373566631*a + 408 3593885), 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, 0, 0, 0, 0, 0, 0], a/x, (x + a)/(x + 4294967310*a), 4204026293*a^2 + 2068287144*a + 232863018, 61489147356178460 11, a, [x + (268392743*a^2 + 2459390605*a + 1304316255), 1; x + (4026574568* a^2 + 1835576706*a + 2990651057), 1], [268392743*a^2 + 2459390605*a + 130431 6254, 4026574568*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)]] 1 ? test2(3) [2, [2, Mat([2, 1])]] 1 ? test2(46744073709551653) [2, [46744073709551652, [2, 2; 3, 1; 7, 1; 37, 1; 1036513, 1; 14510113, 1]]] *** at top-level: test2(46744073709551 *** ^-------------------- *** in function test2: ...d(1,p)),&o);print([g,o]);fflog(g^17,g,o) *** ^--------------- *** fflog: gen_Shanks_log: supplied order (= 2) is incorrect. ? test2(precprime(1<<32)) [2, [4294967290, [2, 1; 5, 1; 19, 1; 22605091, 1]]] 17 ? 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(ffinit(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(ffinit(7,4));fflog(t^6,t^2) *** at top-level: t=ffgen(ffinit(7,4));fflog(t^6,t^2) *** ^-------------- *** fflog: gen_Shanks_log: supplied order (= 5) is incorrect. ? t=ffgen(ffinit(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) []~ ? print("Total time spent: ",gettime); Total time spent: 1100 pari-2.5.5/src/test/64/sumiter0000644000175000017500000000232012147140047014513 0ustar billbill realprecision = 19 significant digits echo = 1 (on) ? gettime;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.0000098157493066238697591433298145196 ? prodinf(n=0,(1+2^-n)/(1+2^(-n+1))) 0.33333333333333333333333333333333333320 ? prodinf(n=0,-2^-n/(1+2^(-n+1)),1) 0.33333333333333333333333333333333333320 ? 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) 1.0000000000000000000000000000000000000 ? 6/Pi^2*sumpos(n=1,n^-2) 1.0000000000000000000000000000000000000 ? getheap [20, 170] ? print("Total time spent: ",gettime); Total time spent: 24 pari-2.5.5/src/test/64/compat0000644000175000017500000026522412212100640014310 0ustar billbill echo = 1 (on) ? default(compatible,3) *** default: Warning: user functions re-initialized. ? gettime;+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=57 realprecision = 57 significant digits ? pi 3.14159265358979323846264338327950288419716939937510582098 ? \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, [0.83756543528332303 544481089907503024040, 0.26959443640544455826293795134926000405, -1.10715987 16887675937077488504242902445]~, 2.9934586462319596298320099794525081778, -2 .4513893819867900608542248318665252254*I, 0.94263855591362295176518779416067 539931, 1.3270305788796764757190502098362372906*I, 7.33813274078957673907072 10033323055880] ? 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.072312766896812300380582649294307897075 + 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]]], [-2.428 5174907194186068992069565359418365, 1.9647119211288133163138753392090569931 + 0.80971492418897895128294082219556466857*I, -0.750453175769104012864271860 94108607489 + 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.54930614433405484569762261846126285233 ? 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, [4.1231056256176605 498214098559740770251, 0.E-57, -4.1231056256176605498214098559740770251]~, 1 .2913084409290072207105564235857096010, -1.291308440929007220710556423585709 6010*I, 2.4328754881596176532948539893637583869, 2.4328754881596176532948539 893637583869*I, 1.6674774896145033307120230298772362382] ? 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.0045457500000000000000000000000000000001 ? 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, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.71246530518434397468087951060 61300701 - 3.1415926535897932384626433832795028843*I; 2.71246530518434397468 08795106061300701 - 6.2831853071795864769252867665590057684*I], [-0.92212354 848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.70148550268542821846861610071436 900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.50057980363245 587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.623 6090511720428168202836906902792025, -0.5788359042095875039617797232424909750 4, -0.34328764427702709438988786673341921877 + 3.141592653589793238462643383 2795028842*I, 0.066178301882745732185368492323164193427 + 3.1415926535897932 384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.922123 54848661459835166758997591019383, 1.4227033521190704721778709033666269682, - 0.70148550268542821846861610071436900869 + 3.1415926535897932384626433832795 028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.6236090511720 428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.5788 3590420958750396177972324249097504, 0.34328764427702709438988786673341921877 , -0.066178301882745732185368492323164193427, 0.9883018503693603305370360822 9907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57 ; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, - 2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0] ]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.066372975210777963595931024670 5326059; 1, 8.0663729752107779635959310246705326059], [1, -7.066372975210777 9635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.06637297521077796359 59310246705326059], [1, x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [ 3], [[3, 2; 0, 1]]], 2.7124653051843439746808795106061300701, 1, [2, -1], [x + 7]], [mat(1), [[0, 0]], [[-0.92212354848661459835166758997591019383 + 3.1 415926535897932384626433832795028842*I, 0.9221235484866145983516675899759101 9383]]], 0] ? buchcertify(bnf) 1 ? buchfu(bnf) [x + 7] ? setrand(1);buchinitforcefu(x^2-x-100000) [mat(5), mat([3, 2, 1, 2, 0, 3, 2, 3, 3, 2, 0, 0, 4, 1, 3, 2, 2, 3]), [-129. 82045011403975460991182396195022419 - 3.624180943686747091 E-113*I; 129.8204 5011403975460991182396195022419 + 1.2486673839592994179 E-113*I], [-41.81126 4589129943393339502258694361489 + 6.2831853071795864769252867665590057684*I, 9.2399004147902289816376260438840931575, -11.874609881075406725097315997431 161032 + 3.1415926535897932384626433832795028842*I, 0, 598.05108556627860067 458199150717266631 + 2.079081953128979844 E-112*I, -194.73067517105963191486 773594292533629 + 3.1415926535897932384626433832795028842*I, -289.5775549361 3404588806583418516364884 + 3.1415926535897932384626433832795028842*I, 102.9 8937362955842429020308089254908188 + 3.898278662116837207 E-113*I, -404.4415 3844676787690336623107514389175 + 3.1415926535897932384626433832795028842*I, 484.20828704532476310708802954016117339 + 3.1415926535897932384626433832795 028842*I, 123.08269893574406654913158801089558608 + 3.898278662116837207 E-1 13*I, -731.25438161267029366213802528899365727 + 6.2831853071795864769252867 665590057684*I, 601.43393149863053905222620132704343308 + 2.0790819531289798 44 E-112*I, 1093.4420050106303665241166125712749392 + 3.14159265358979323846 26433832795028842*I, -745.79191925764104608772064294411862807 + 3.1415926535 897932384626433832795028842*I, -671.20676609281265093040971423356733550 + 6. 2831853071795864769252867665590057684*I, 239.9341511615634437073347400890223 0144 + 3.1415926535897932384626433832795028842*I, 652.9785442166766555563076 0228878662857 + 3.1415926535897932384626433832795028842*I, -1733.35340971812 46358289416962430827836 + 6.2831853071795864769252867665590057684*I; 41.8112 64589129943393339502258694361489 + 8.933555267351085266 E-114*I, -9.23990041 47902289816376260438840931575 + 3.1415926535897932384626433832795028842*I, 1 1.874609881075406725097315997431161032 + 2.030353469852519379 E-115*I, 0, -5 98.05108556627860067458199150717266631 + 3.141592653589793238462643383279502 8842*I, 194.73067517105963191486773594292533629 + 3.248565551764031006 E-113 *I, 289.57755493613404588806583418516364884 + 4.547991772469643408 E-113*I, -102.98937362955842429020308089254908188 + 3.1415926535897932384626433832795 028842*I, 404.44153844676787690336623107514389175 + 6.497131103528062012 E-1 13*I, -484.20828704532476310708802954016117339 + 6.2831853071795864769252867 665590057684*I, -123.08269893574406654913158801089558608 + 3.141592653589793 2384626433832795028842*I, 731.25438161267029366213802528899365727 + 1.299426 2207056124024 E-112*I, -601.43393149863053905222620132704343308 + 6.28318530 71795864769252867665590057684*I, -1093.4420050106303665241166125712749392 + 3.1415926535897932384626433832795028842*I, 745.79191925764104608772064294411 862807 + 3.1415926535897932384626433832795028842*I, 671.20676609281265093040 971423356733550 + 3.1415926535897932384626433832795028842*I, -239.9341511615 6344370733474008902230144 + 6.2831853071795864769252867665590057684*I, -652. 97854421667665555630760228878662857 + 3.141592653589793238462643383279502884 2*I, 1733.3534097181246358289416962430827836 + 2.598852441411224805 E-112*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, 1000 00; 1, 4]], [13, [5, 1]~, 1, 1, [-6, 100000; 1, -5]], [31, [23, 1]~, 1, 1, [ 7, 100000; 1, 8]], [31, [38, 1]~, 1, 1, [-8, 100000; 1, -7]], [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]], [29, [-14, 1]~, 1, 1, [13, 100000; 1, 14]], [29, [13, 1]~, 1, 1, [-14, 1000 00; 1, -13]], [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.7281613012984016139208 9489603747004], [1, -315.72816130129840161392089489603747004; 1, 316.7281613 0129840161392089489603747004], [1, -316; 1, 317], [2, 1; 1, 200001], [400001 , 200000; 0, 1], [200001, -1; -1, 2], [400001, [200000, 100000; 1, 200001]]] , [-315.72816130129840161392089489603747004, 316.728161301298401613920894896 03747004], [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], [379554 884019013781006303254896369154068336082609238336*x + 11983616564425078999046 2835950022871665178127611316131167]], [mat(1), [[0, 0]], [[-41.8112645891299 43393339502258694361489 + 6.2831853071795864769252867665590057684*I, 41.8112 64589129943393339502258694361489 + 8.933555267351085266 E-114*I]]], 0] ? setrand(1);bnf=buchinitfu(x^2-x-57,0.2,0.2) [mat(3), mat([1, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.71246530518434397468087951060 61300701 - 3.1415926535897932384626433832795028843*I; 2.71246530518434397468 08795106061300701 - 6.2831853071795864769252867665590057684*I], [-0.92212354 848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.70148550268542821846861610071436 900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.50057980363245 587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.623 6090511720428168202836906902792025, -0.5788359042095875039617797232424909750 4, -0.34328764427702709438988786673341921877 + 3.141592653589793238462643383 2795028842*I, 0.066178301882745732185368492323164193427 + 3.1415926535897932 384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.922123 54848661459835166758997591019383, 1.4227033521190704721778709033666269682, - 0.70148550268542821846861610071436900869 + 3.1415926535897932384626433832795 028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.6236090511720 428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.5788 3590420958750396177972324249097504, 0.34328764427702709438988786673341921877 , -0.066178301882745732185368492323164193427, 0.9883018503693603305370360822 9907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 57 ; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, - 2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0] ]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.066372975210777963595931024670 5326059; 1, 8.0663729752107779635959310246705326059], [1, -7.066372975210777 9635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.06637297521077796359 59310246705326059], [1, x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [ 3], [[3, 2; 0, 1]]], 2.7124653051843439746808795106061300701, 1, [2, -1], [x + 7]], [mat(1), [[0, 0]], [[-0.92212354848661459835166758997591019383 + 3.1 415926535897932384626433832795028842*I, 0.9221235484866145983516675899759101 9383]]], 0] ? setrand(1);buchreal(10^9-3,0,0.5,0.5) [4, [4], [qfr(283, 31285, -18771, 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.229975145405511722395637833443108787] [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], [[17, 2; 0, 1]]]] [129.82045011403975460991182396194763531] [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, 4, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]]]] [3.7941269688216589341408274220859400302] [1] [[6, 10/1029*x^3 - 13/343*x^2 + 165/343*x + 1478/343]] [[4/1029*x^3 + 53/1029*x^2 + 66/343*x + 111/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, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.7124653051843439746808795106 061300701 - 3.1415926535897932384626433832795028843*I; 2.7124653051843439746 808795106061300701 - 6.2831853071795864769252867665590057684*I], [-0.9221235 4848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.7014855026854282184686161007143 6900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.5005798036324 5587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.62 36090511720428168202836906902792025, -0.578835904209587503961779723242490975 04, -0.34328764427702709438988786673341921877 + 3.14159265358979323846264338 32795028842*I, 0.066178301882745732185368492323164193427 + 3.141592653589793 2384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.92212 354848661459835166758997591019383, 1.4227033521190704721778709033666269682, -0.70148550268542821846861610071436900869 + 3.141592653589793238462643383279 5028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.623609051172 0428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.578 83590420958750396177972324249097504, 0.3432876442770270943898878667334192187 7, -0.066178301882745732185368492323164193427, 0.988301850369360330537036082 29907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 5 7; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, -2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0 ]]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.06637297521077796359593102467 05326059; 1, 8.0663729752107779635959310246705326059], [1, -7.06637297521077 79635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7 ; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.0663729752107779635 959310246705326059], [1, x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2.7124653051843439746808795106061300701, 1, [2, -1], [ x + 7]], [mat(1), [[0, 0]], [[-0.92212354848661459835166758997591019383 + 3. 1415926535897932384626433832795028842*I, 0.922123548486614598351667589975910 19383]]], [0, [mat([[5, 1]~, 1])]]], [[[5, 3; 0, 1], [1, 0]], [8, [4, 2], [2 , [-4, 0]~]], mat([[5, [-2, 1]~, 1, 1, [1, 1]~], 1]), [[[[4], [[2, 0]~], [[2 , 0]~], [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, 2, 1, 2, 1, 2, 1, 1, 2]), [-2.7124653051843439746808795106 061300701 - 3.1415926535897932384626433832795028843*I; 2.7124653051843439746 808795106061300701 - 6.2831853071795864769252867665590057684*I], [-0.9221235 4848661459835166758997591019383 + 3.1415926535897932384626433832795028842*I, -1.4227033521190704721778709033666269682, 0.7014855026854282184686161007143 6900869 + 3.1415926535897932384626433832795028842*I, 0.E-38, 0.5005798036324 5587382620331339071677438 + 3.1415926535897932384626433832795028842*I, -1.62 36090511720428168202836906902792025, -0.578835904209587503961779723242490975 04, -0.34328764427702709438988786673341921877 + 3.14159265358979323846264338 32795028842*I, 0.066178301882745732185368492323164193427 + 3.141592653589793 2384626433832795028842*I, -0.98830185036936033053703608229907438725; 0.92212 354848661459835166758997591019383, 1.4227033521190704721778709033666269682, -0.70148550268542821846861610071436900869 + 3.141592653589793238462643383279 5028842*I, 0.E-38, -0.50057980363245587382620331339071677436, 1.623609051172 0428168202836906902792025 + 3.1415926535897932384626433832795028842*I, 0.578 83590420958750396177972324249097504, 0.3432876442770270943898878667334192187 7, -0.066178301882745732185368492323164193427, 0.988301850369360330537036082 29907438725], [[3, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [5, [-2, 1]~, 1, 1, [1, 5 7; 1, 2]], [11, [-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]], [11, [1, 1]~, 1, 1, [-2, 57; 1, -1]], [17, [-3, 1]~, 1, 1, [2, 57; 1, 3]], [17, [2, 1]~, 1, 1, [-3, 57; 1, -2]], [19, [-1, 1]~, 1, 1, [0, 57; 1, 1]], [19, [0, 1]~, 1, 1, [-1, 57; 1, 0 ]]], 0, [x^2 - x - 57, [2, 0], 229, 1, [[1, -7.06637297521077796359593102467 05326059; 1, 8.0663729752107779635959310246705326059], [1, -7.06637297521077 79635959310246705326059; 1, 8.0663729752107779635959310246705326059], [1, -7 ; 1, 8], [2, 1; 1, 115], [229, 114; 0, 1], [115, -1; -1, 2], [229, [114, 57; 1, 115]]], [-7.0663729752107779635959310246705326059, 8.0663729752107779635 959310246705326059], [1, x], [1, 0; 0, 1], [1, 0, 0, 57; 0, 1, 1, 1]], [[3, [3], [[3, 2; 0, 1]]], 2.7124653051843439746808795106061300701, 1, [2, -1], [ x + 7]], [mat(1), [[0, 0]], [[-0.92212354848661459835166758997591019383 + 3. 1415926535897932384626433832795028842*I, 0.922123548486614598351667589975910 19383]]], [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, 1]~], 2]), [[[[4 ], [[2, 0]~], [[2, 0]~], [Vecsmall([0, 0])], 1], [[5], [[6, 0]~], [[6, 0]~], [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]], [1], mat([1, -3, -6, -6]), [12, [12], [[3, 2; 0, 1]]], [[0, 2, 0; -1, 10, 0], [- 2, 0; 0, -10], 2]] ? bytesize(%) 12672 ? 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, [-0.1624345647 1667696455518910092496975960, -0.73040556359455544173706204865073999595, -2. 1071598716887675937077488504242902445]~, -2.99345864623195962983200997945250 81778, 2.4513893819867900608542248318665252254*I, -0.94263855591362295176518 779416067539931, -1.3270305788796764757190502098362372906*I, 7.3381327407895 767390707210033323055880] ? 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 698368 + 0.18258225455744299269398828369501930574*I, 0.460202188254280606994 79112458168698368 - 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]) [mod(6, 7), mod(5, 7)]~ ? 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.2833494518006402717978106547571267252 1 0.283349451800640271797810654757 12672521] [-0.14167472590032013589890532737856336261 -2 0.6416747259003201358989053273 7856336260] [1 1 1] ? eint1(2) 0.048900510708061119567239835228049522312 ? 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 - 2*x^4 - 62*x^3 + 85*x^2 + 818*x + 1, x^5 - 2*x^4 - 53*x^3 - 46 *x^2 + 508*x + 913, x^5 - 2*x^4 - 13*x^3 + 37*x^2 - 21*x - 1, x^5 - x^4 - 52 *x^3 - 197*x^2 - 273*x - 127] ? factoredpolred2(p,fa) [x - 1, x^5 - 2*x^4 - 62*x^3 + 85*x^2 + 818*x + 1, x^5 - 2*x^4 - 53*x^3 - 46 *x^2 + 508*x + 913, x^5 - 2*x^4 - 13*x^3 + 37*x^2 - 21*x - 1, x^5 - x^4 - 52 *x^3 - 197*x^2 - 273*x - 127] ? 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 ? getheap() [208, 44472] ? 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, -75886057790445 87579, 6326125408131455503, 7732749207731402837, -1613588760277891043, 15044 84430693122605, 3559908810877183593, 398392693500313604, -522733760525442566 2, -8538285792856111966, -1016248616502867779, 6383722513257788241, -1547136 224174182884, 2139025113908673680, -8649952375285170822, 7159506599077310177 , -8545857881376569117, 8750587220496604824, -6606875118057441902, -81411652 63118337473, 44, 2480910733597539216]) ? getstack() 200 ? globalred(acurve) [37, [1, -1, 2, 2], 1] ? getstack() 200 ? 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 837196 - 1.5701452385894131769052374806001981109*I; 1, 1.6829412935943127761 629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.750453175 76910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, - 0.78742068874775359433940488309213323160 + 2.1336633893126618034168454610457 936016*I, 1.2658732110596551455718089553258673705 - 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]]], [-1.0891151457205048250249527946671612684, -0.13838372073406036365047 976417441696637 + 0.49181637657768643499753285514741525107*I, 1.682941293594 3127761629561615079976006 + 2.0500351226010726172974286983598602164*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 2837196 - 1.5701452385894131769052374806001981109*I; 1, 1.682941293594312776 1629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.75045317 576910401286427186094108607490 + 1.3101462685358123283560773619310445915*I, -0.78742068874775359433940488309213323160 + 2.133663389312661803416845461045 7936016*I, 1.2658732110596551455718089553258673705 - 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]]], [-1.0891151457205048250249527946671612684, -0.1383837207340603636504 7976417441696637 + 0.49181637657768643499753285514741525107*I, 1.68294129359 43127761629561615079976006 + 2.0500351226010726172974286983598602164*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, -1, -1, -1, 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, -1, -1, -1, 0]~] 1] [[5, [-1, 0, 0, 0, 2]~, 4, 1, [2, 2, 1, 2, 1]~] 3] [[5, [2, 0, 0, 0, -2]~, 1, 1, [2, 0, 3, 0, 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, [1.0000000000000000000000000 000000000000, 0.E-57, -1.0000000000000000000000000000000000000]~, 2.62205755 42921198104648395898911194137, -2.6220575542921198104648395898911194137*I, 1 .1981402347355922074399224922803238782, 1.1981402347355922074399224922803238 782*I, 6.8751858180203728274900957798105571979] ? 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.047197551196597745 ? 2*intopen(x=0,100,sin(x)/x) 3.124450933778112631 ? \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 840494514780771076350, 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, [1.732050807568877294, 0. E-38, -1.732050807568877294]~, 1.992332899583490707, -1.992332899583490707*I , 1.576841226808312136, 1.576841226808312137*I, 3.969390382762759666] ? 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, [0.8375654352833230 354, 0.2695944364054445583, -1.107159871688767594]~, 2.993458646231959630, - 2.451389381986790061*I, 0.9426385559136229515, 1.327030578879676476*I, 7.338 132740789576739] ? l=lseriesell(ccurve,2,-37,1) 0.3815754082607112087 ? lseriesell(ccurve,2,-37,1.2)-l 2.466559942404522587 E-18 ? 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, 1, 1]), [9, 15, 16, 33, 39, 17, 10, 57, 69], [2, -1], [[0, 1, 0]~, [ 5, 3, 1]~], [[[4, -1, 0]~, [1, -1, 0]~, [-2, -1, 0]~, [1, 1, 0]~, [10, 5, 1] ~, [3, 1, 0]~, [3, 0, 0]~, [7, 2, 0]~, [-2, -1, 1]~], 0]] ? makebigbnf(sbnf) [mat(2), mat([1, 1, 0, 1, 0, 1, 1, 1]), [1.173637103435061715 + 3.1415926535 89793239*I, -4.562279014988837911 + 3.141592653589793239*I; -2.6335434327389 76050 + 3.141592653589793239*I, 1.420330600779487358 + 3.141592653589793239* I; 1.459906329303914335, 3.141948414209350544], [1.246346989334819161, 0.540 4006376129469728, -0.6926391142471042845, 0.004375616572659815434 + 3.141592 653589793239*I, -0.8305625946607188642 + 3.141592653589793239*I, -1.99005644 5584799713 + 3.141592653589793239*I, 0, -1.977791147836553954, 0.36772620140 27817707; 0.6716827432867392935, -0.8333219883742404172, -0.2461086674077943 078 + 3.141592653589793239*I, -0.8738318043071131266, -1.552661549868775854, 0.5379005671092853266, 0, 0.5774919091398324094, 0.9729063188316092381 + 3. 141592653589793239*I; -1.918029732621558454 + 3.141592653589793239*I, 0.2929 213507612934446 + 3.141592653589793239*I, 0.9387477816548985924 + 3.14159265 3589793239*I, 0.8694561877344533112, 2.383224144529494719, 1.452155878475514 387, 0, 1.400299238696721545, -1.340632520234391008 + 3.141592653589793239*I ], [[3, [-1, 1, 0]~, 1, 1, [1, 1, 1]~], [5, [-1, 1, 0]~, 1, 1, [0, 1, 1]~], [5, [2, 1, 0]~, 1, 1, [1, -2, 1]~], [11, [1, 1, 0]~, 1, 1, [-3, -1, 1]~], [1 3, [19, 1, 0]~, 1, 1, [-2, -6, 1]~], [5, [3, 1, 0]~, 1, 1, [2, 2, 1]~], [3, [10, 1, 1]~, 1, 2, [-1, 1, 0]~], [19, [-6, 1, 0]~, 1, 1, [6, 6, 1]~], [23, [ -10, 1, 0]~, 1, 1, [-7, 10, 1]~]]~, 0, [x^3 - x^2 - 14*x - 1, [3, 0], 10889, 1, [[1, -3.233732695981516673, 4.690759845041404812; 1, -0.0718235090274363 6345, -8.923017874523549404; 1, 4.305556205008953037, 5.232258029482144592], [1, -3.233732695981516673, 4.690759845041404812; 1, -0.07182350902743636345 , -8.923017874523549404; 1, 4.305556205008953037, 5.232258029482144592], [1, -3, 5; 1, 0, -9; 1, 4, 5], [3, 1, 1; 1, 29, 8; 1, 8, 129], [10889, 5698, 89 94; 0, 1, 0; 0, 0, 1], [3677, -121, -21; -121, 386, -23; -21, -23, 86], [108 89, [1899, 46720, 5235; 5191, 7095, 25956; 1, 5191, 1895]]], [-3.23373269598 1516673, -0.07182350902743636345, 4.305556205008953037], [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.34800724602768001, 1, [2, -1], [x, x^2 + 2*x - 4]], [mat(1), [[0, 0, 0]], [[1.246346989334819161, 0.6716827432867392935, -1.918029732621558454 + 3.141592653589793239*I]]], [[[4, -1, 0]~, [1, -1, 0]~, [-2, -1, 0]~, [1, 1, 0]~, [10, 5, 1]~, [3, 1, 0]~, [3, 0, 0]~, [7, 2, 0]~, [-2, -1, 1]~], 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.4476973883408951693] [0.4476973883408951693 1.755026016172950714] ? gauss(ma,mhbi) [-1.000000000000000000, 1.000000000000000000]~ ? (1.*hilbert(7))^(-1) [49.00000000002269496 -1176.000000000891987 8820.000000008509233 -29400.0000 0003284322 48510.00000005988659 -38808.00000005152288 12012.00000001685498] [-1176.000000000891948 37632.00000003510563 -317520.0000003351516 1128960.00 0001294390 -1940400.000002361054 1596672.000002032041 -504504.0000006650229] [8820.000000008508983 -317520.0000003351867 2857680.000003201679 -10584000.0 0001236988 18711000.00002256953 -15717240.00001942843 5045040.000006359405] [-29400.00000003285047 1128960.000001294815 -10584000.00001237252 40320000.0 0004781419 -72765000.00008725574 62092800.00007512232 -20180160.00002459211] [48510.00000005991011 -1940400.000002362406 18711000.00002257993 -72765000.0 0008727736 133402500.0001592931 -115259760.0001371561 37837800.00004490309] [-38808.00000005155726 1596672.000002033708 -15717240.00001944225 62092800.0 0007515994 -115259760.0001371910 100590336.0001181345 -33297264.00003867797] [12012.00000001687298 -504504.0000006657397 5045040.000006365508 -20180160.0 0002461053 37837800.00004492566 -33297264.00003868758 11099088.00001266713] ? 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 modulo: 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);a=matrix(3,5,j,k,vvector(5,l,random()\10^8)) [[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, 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]]] ? 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, 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]]] ? 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]~ ? setrand(1);as=matrix(3,3,j,k,vvector(5,l,random()\10^8)) [[15, 8, 17, 7, 12]~ [1, 4, 10, 6, 4]~ [1, 12, 9, 11, 11]~] [[16, 15, 20, 18, 14]~ [0, 3, 21, 15, 8]~ [10, 0, 18, 0, 7]~] [[11, 11, 12, 7, 2]~ [9, 20, 11, 7, 16]~ [0, 12, 3, 12, 2]~] ? nfsmith(nf,[as,[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 - 363*x - 2663, 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) [4, 7, 1, 6, 3, 5, 2] ? permutation2num([4,7,1,6,3,5,2]) 1035 ? pf(-44,3) qfi(3, 2, 4) ? phi(257^2) 65792 ? pi 3.141592653589793239 ? b=10;a=1<1e-18,f(x),subst(F,t,x)); ? intnum(x=0,[oo,1],f(x))-Euler 0.E-96 ? intnum(x=0,[oo,1],g(x))-Euler 0.E-96 ? intnum(x=0,1,1/sqrt(x))-2 -1.9262844386075338042 E-59 ? intnum(x=[0,-1/2],1,1/sqrt(x))-2 0.E-95 ? intnum(x=0,[oo,1],sin(x)/x)-Pi/2 0.00429640980192847594663632193954407532716512471317646262273262828586471032 064716268232582299149210 ? intnum(x=0,[oo,-I],sin(x)/x)-Pi/2 0.E-96 ? intnum(x=0,[oo,-2*I],sin(2*x)/x)-Pi/2 0.E-96 ? 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 -9.363352709384396655 E-97 ? intnum(x=0,[oo,1],sin(x)^3*exp(-x))-0.3 0.E-96 ? intnum(x=0,[oo,-I],sin(x)^3*exp(-x))-0.3 -1.3352846492208801743 E-89 ? tab=intnuminit(0,[oo,-I],m+1); ? intnum(x=0,oo,sin(x)^3*exp(-x),tab)-0.3 0.E-96 ? intnum(x=0,[oo,-I],x^2*sin(x))+2 0.E-95 ? tab=intnuminit(-1,1); ? intnum(x=-1,1,intnum(y=-sqrt(1-x^2),sqrt(1-x^2),x^2+y^2,tab),tab)-Pi/2 -1.7790370147830353644 E-94 ? \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); ? a-b -1.0040645786513746241 E-306 + 0.E-350*I ? sumnum(n=1,2,1/(n^3+n+1),tab,1)-a 1.0040645786513746241 E-306 ? c=sumnum(n=1,2,1/(n^2+1),tab,1); ? d=sumpos(n=1,1/(n^2+1)); ? d-c 1.9691903647788732240 E-306 ? sumnum(n=1,2,n^(-4/3),,1)-zeta(4/3) -1.5810786927596923975695032330081859885853923189652965380063515132600239871 9095595253532786696377207848456709735455733654166843737571750244058595083139 34284299570579730419329071710335445546831167530844494561104269 E-110 ? tab=sumnuminit([2,-3/2]); ? sumnum(n=1,[2,-3/2],1/(n*sqrt(n)),tab,1)-zeta(3/2) -1.1904145143013527400 E-305 ? suminf(n=1,2^(-n))-1 -1.1125369292536006916 E-308 ? sumpos(n=1,2^(-n))-1 -2.781342323134001729 E-308 ? sumnum(n=1,[2,log(2)],2^(-n),intnumstep()+1,1)-1 -1.9519460423754424134 E-305 ? 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)); ? a-b -1.3906711615670008645 E-308 ? print("Total time spent: ",gettime); Total time spent: 14194 pari-2.5.5/src/test/64/nfhilbert0000644000175000017500000000044312147140047015004 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 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] Total time spent: 1260 pari-2.5.5/src/test/64/member0000644000175000017500000002605712147140047014307 0ustar billbillNF .diff: [1105, 553; 0, 1] .codiff: [1, 553/1105; 0, 1/1105] .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]]], [-33.241540277189322804630581542105218897, 33.24154027718932280 4630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0, 1, 1 , -1]] .pol: y^2 - 1105 .roots: [-33.241540277189322804630581542105218897, 33.2415402771893228046305 81542105218897] .sign: [2, 0] .r1: 2 .r2: 0 .t2: [2, -1.0000000000000000000000000000000000000; -1.0000000000000000000000 000000000000000, 552.99999999999999999999999999999999998] .zk: [1, 1/2*y - 1/2] BNF .bnf: [[2, 0; 0, 2], [1, 1, 0, 1, 0, 1, 1; 1, 0, 1, 1, 1, 0, 1], [-10.950385 405825605330267750825017937393 + 3.1415926535897932384626433832795028842*I; 10.950385405825605330267750825017937393], [8.1433720041619460221749001672695 803069 + 3.1415926535897932384626433832795028842*I, 4.4847567981443655473417 848269834687859 + 3.1415926535897932384626433832795028842*I, -1.343048075374 9138388048557277007612130, 0.E-37, 21.900770811651210660535501650035874786 + 1.8807909613156600130000000000000000000 E-37*I, 28.214835212804366445293844 147162399333 + 1.8807909613156600130000000000000000000 E-37*I, -8.7080070067 534225565968584115262030002 + 6.2831853071795864769252867665590057684*I, 4.0 716860020809730110874500836347901535 + 2.35098870164457501600000000000000000 00 E-38*I, -7.9295939339699852522139609280820644804 + 3.14159265358979323846 26433832795028841*I; -8.1433720041619460221749001672695803069 + 3.1415926535 897932384626433832795028841*I, -4.4847567981443655473417848269834687859 + 3. 1415926535897932384626433832795028842*I, 1.343048075374913838804855727700761 2130 + 3.1415926535897932384626433832795028842*I, 0.E-37, -21.90077081165121 0660535501650035874786 + 6.2831853071795864769252867665590057684*I, -28.2148 35212804366445293844147162399333 + 6.2831853071795864769252867665590057682*I , 8.7080070067534225565968584115262030002 + 3.141592653589793238462643383279 5028842*I, -4.0716860020809730110874500836347901535 + 3.14159265358979323846 26433832795028842*I, 7.9295939339699852522139609280820644804 + 4.70197740328 91500320000000000000000000 E-38*I], [[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], [ 3, [0, 2]~, 1, 1, [-1, -276; -1, 0]], [11, [8, 2]~, 1, 1, [5, 552; 2, 3]], [ 2, [2, 1]~, 1, 1, [1, 276; 1, 0]], [3, [2, 2]~, 1, 1, [0, -276; -1, 1]], [5, [1, 2]~, 2, 1, [1, 552; 2, -1]], [17, [1, 2]~, 2, 1, [1, 552; 2, -1]], [13, [1, 2]~, 2, 1, [1, 552; 2, -1]], [11, [16, 2]~, 1, 1, [-3, 552; 2, -5]]], 0 , [y^2 - 1105, [2, 0], 1105, 2, [[1, -17.12077013859466140231529077105260944 8; 1, 16.120770138594661402315290771052609448], [1, -17.12077013859466140231 5290771052609448; 1, 16.120770138594661402315290771052609448], [1, -17; 1, 1 6], [2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1 , 552]]], [-33.241540277189322804630581542105218897, 33.24154027718932280463 0581542105218897], [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.950385405825605330267750 825017937393, 1, [2, -1], [857*y + 28488]], [[-1, 0; 0, -1], [[0, 0], [0, 0] ], [[-8.1433720041619460221749001672695803069 - 3.14159265358979323846264338 32795028842*I, 8.1433720041619460221749001672695803069 - 3.14159265358979323 84626433832795028841*I], [-4.4847567981443655473417848269834687859 - 3.14159 26535897932384626433832795028842*I, 4.4847567981443655473417848269834687859 - 3.1415926535897932384626433832795028842*I]]], 0] .clgp: [4, [2, 2], [[2, 0; 0, 1], [3, 1; 0, 1]]] .cyc: [2, 2] .diff: [1105, 553; 0, 1] .codiff: [1, 553/1105; 0, 1/1105] .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]]], [-33.241540277189322804630581542105218897, 33.24154027718932280 4630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0, 1, 1 , -1]] .no: 4 .pol: y^2 - 1105 .reg: 10.950385405825605330267750825017937393 .roots: [-33.241540277189322804630581542105218897, 33.2415402771893228046305 81542105218897] .sign: [2, 0] .r1: 2 .r2: 0 .t2: [2, -1.0000000000000000000000000000000000000; -1.0000000000000000000000 000000000000000, 552.99999999999999999999999999999999998] .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, 1]~], 2; [2, [2, 1]~, 1, 1, [1, 1]~], 2], [[[[1], [[1, 0]~], [[1, 0]~], [Vecsmall([])], 1], [[2], [[-1, 0]~], [[1, -2]~], [Vecsmall([])] , Mat([1/2, -1/2])]], [[[1], [[1, 0]~], [[1, 0]~], [Vecsmall([])], 1], [[2], [[-1, 0]~], [[-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, 1; 1, 0, 1, 1, 1, 0, 1], [-10.950385 405825605330267750825017937393 + 3.1415926535897932384626433832795028842*I; 10.950385405825605330267750825017937393], [8.1433720041619460221749001672695 803069 + 3.1415926535897932384626433832795028842*I, 4.4847567981443655473417 848269834687859 + 3.1415926535897932384626433832795028842*I, -1.343048075374 9138388048557277007612130, 0.E-37, 21.900770811651210660535501650035874786 + 1.8807909613156600130000000000000000000 E-37*I, 28.214835212804366445293844 147162399333 + 1.8807909613156600130000000000000000000 E-37*I, -8.7080070067 534225565968584115262030002 + 6.2831853071795864769252867665590057684*I, 4.0 716860020809730110874500836347901535 + 2.35098870164457501600000000000000000 00 E-38*I, -7.9295939339699852522139609280820644804 + 3.14159265358979323846 26433832795028841*I; -8.1433720041619460221749001672695803069 + 3.1415926535 897932384626433832795028841*I, -4.4847567981443655473417848269834687859 + 3. 1415926535897932384626433832795028842*I, 1.343048075374913838804855727700761 2130 + 3.1415926535897932384626433832795028842*I, 0.E-37, -21.90077081165121 0660535501650035874786 + 6.2831853071795864769252867665590057684*I, -28.2148 35212804366445293844147162399333 + 6.2831853071795864769252867665590057682*I , 8.7080070067534225565968584115262030002 + 3.141592653589793238462643383279 5028842*I, -4.0716860020809730110874500836347901535 + 3.14159265358979323846 26433832795028842*I, 7.9295939339699852522139609280820644804 + 4.70197740328 91500320000000000000000000 E-38*I], [[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], [ 3, [0, 2]~, 1, 1, [-1, -276; -1, 0]], [11, [8, 2]~, 1, 1, [5, 552; 2, 3]], [ 2, [2, 1]~, 1, 1, [1, 276; 1, 0]], [3, [2, 2]~, 1, 1, [0, -276; -1, 1]], [5, [1, 2]~, 2, 1, [1, 552; 2, -1]], [17, [1, 2]~, 2, 1, [1, 552; 2, -1]], [13, [1, 2]~, 2, 1, [1, 552; 2, -1]], [11, [16, 2]~, 1, 1, [-3, 552; 2, -5]]], 0 , [y^2 - 1105, [2, 0], 1105, 2, [[1, -17.12077013859466140231529077105260944 8; 1, 16.120770138594661402315290771052609448], [1, -17.12077013859466140231 5290771052609448; 1, 16.120770138594661402315290771052609448], [1, -17; 1, 1 6], [2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1 , 552]]], [-33.241540277189322804630581542105218897, 33.24154027718932280463 0581542105218897], [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.950385405825605330267750 825017937393, 1, [2, -1], [857*y + 28488]], [[-1, 0; 0, -1], [[0, 0], [0, 0] ], [[-8.1433720041619460221749001672695803069 - 3.14159265358979323846264338 32795028842*I, 8.1433720041619460221749001672695803069 - 3.14159265358979323 84626433832795028841*I], [-4.4847567981443655473417848269834687859 - 3.14159 26535897932384626433832795028842*I, 4.4847567981443655473417848269834687859 - 3.1415926535897932384626433832795028842*I]]], [0, [Mat([[16, -1]~, 1]), Ma t([[-137, -8]~, 1])]]] .clgp: [4, [2, 2]] .cyc: [2, 2] .diff: [1105, 553; 0, 1] .codiff: [1, 553/1105; 0, 1/1105] .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]]], [-33.241540277189322804630581542105218897, 33.24154027718932280 4630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0, 1, 1 , -1]] .no: 4 .pol: y^2 - 1105 .roots: [-33.241540277189322804630581542105218897, 33.2415402771893228046305 81542105218897] .sign: [2, 0] .r1: 2 .r2: 0 .t2: [2, -1.0000000000000000000000000000000000000; -1.0000000000000000000000 000000000000000, 552.99999999999999999999999999999999998] .zk: [1, 1/2*y - 1/2] RNF .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]]], [-33.241540277189322804630581542105218897, 33.24154027718932280 4630581542105218897], [1, 1/2*y - 1/2], [1, 1; 0, 2], [1, 0, 0, 276; 0, 1, 1 , -1]] .pol: 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])] .mod: 1341068619663964900807 .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 .j: 6128487/10351 .omega: [2.7807400137667297710631976271813584994, 1.390370006883364885531598 8135906792497 - 1.0687497763561930661592635474375038788*I] .eta: [3.1096482423243803285501491221965830079 + 2.3509887016445750160000000 000000000000 E-38*I, 1.5548241211621901642750745610982915040 + 1.06437474521 02737569438859937299427442*I] .roots: [-1.6189099322673713423780009396072169751, -0.3155450338663143288109 9953019639151248 - 2.0925470969119586079816894466366945829*I, -0.31554503386 631432881099953019639151248 + 2.0925470969119586079816894466366945829*I]~ ELLQp .a1: 1 + O(11^2) .a2: 2 + O(11^2) .a3: 3 + O(11^2) .a4: 4 + O(11^2) .a6: 5 + O(11^2) .b2: 9 + O(11^2) .b4: 11 + O(11^2) .b6: 7 + 2*11 + O(11^2) .b8: 2 + 3*11 + O(11^2) .c4: 4 + 5*11 + O(11^2) .c6: 3 + 7*11 + O(11^2) .disc: 5*11 + O(11^2) .j: 4*11^-1 + O(11^0) .roots: [9 + O(11^2)] .tate: [6 + 8*11 + O(11^2), 0, 3*11 + O(11^2)] .w: 1 + 3*11 + O(11^2) SMALLELL .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 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] Total time spent: 52 pari-2.5.5/src/test/64/graph0000644000175000017500000000565212147140053014134 0ustar billbill echo = 1 (on) ? gettime;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]) ? getheap [9, 137] ? print("Total time spent: ",gettime); Total time spent: 12 pari-2.5.5/src/test/64/trans0000644000175000017500000006544412147140047014172 0ustar billbill realprecision = 2003 significant digits (2000 digits displayed) echo = 1 (on) ? gettime;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,20) 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 ? 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 - 5.940911144672 374449 E-213*I ? 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 ? getheap [60, 3954] ? print("Total time spent: ",gettime); Total time spent: 32 pari-2.5.5/src/test/64/polyser0000644000175000017500000001466112147140047014533 0ustar billbill echo = 1 (on) ? gettime;apol=x^3+5*x+1 x^3 + 5*x + 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))*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] ? factorpadic(apol,7,8,1) [(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] ? 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 663382582902335604 + 0.84813118358634026680538906224199030918*I, -0.67063790 319207539268663382582902335604 - 0.84813118358634026680538906224199030918*I, -0.35481882329952371381627468235580237078 + 1.39980287391035466982975228340 62081965*I, -0.35481882329952371381627468235580237078 - 1.399802873910354669 8297522834062081965*I]~ ? polroots(x^4-1000000000000000000000,1) [-177827.94100389228012254211951926848447 + 0.E-38*I, 177827.941003892280122 54211951926848447 + 0.E-38*I, 0.E-98 + 177827.941003892280122542119519268484 47*I, 0.E-98 - 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 ? getheap [58, 7149] ? print("Total time spent: ",gettime); Total time spent: 8 pari-2.5.5/src/test/64/number0000644000175000017500000001253612147140047014325 0ustar billbill echo = 1 (on) ? gettime;addprimes([nextprime(10^9),nextprime(10^10)]) [1000000007, 10000000019] ? bestappr(Pi,10000) 355/113 ? bezout(123456789,987654321) [-8, 1, 9] ? bigomega(12345678987654321) 8 ? binomial(1.1,5) -0.0045457500000000000000000000000000000001 ? 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)]] ? getheap [87, 2686] ? print("Total time spent: ",gettime); Total time spent: 20 pari-2.5.5/src/test/64/objets0000644000175000017500000000415312147140047014317 0ustar billbill echo = 1 (on) ? gettime;+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 698368 + 0.18258225455744299269398828369501930574*I, 0.460202188254280606994 79112458168698368 - 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) [4, 7, 1, 6, 3, 5, 2] ? permtonum([4,7,1,6,3,5,2]) 1035 ? 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 modulo: Mod(131, 49649). ? getheap [59, 784] ? print("Total time spent: ",gettime); Total time spent: 0 pari-2.5.5/src/test/64/random0000644000175000017500000000104312147140047014304 0ustar billbillMod(2, 3) a^2 [[a^2 + 1, a + 1], 1] 3223690774*a^2 + 2495927739*a + 1543932468 [[3721271368*a^2 + 4187301858*a + 3059946484, 1822325213*a^2 + 2600590275*a + 1926122145], 1] 4063307077606482163*a^2 + 2169871353760194456*a + 10598342506117936052 [[4279149226930994438*a^2 + 1866216328193138993*a + 15557795631803490524, 56 18237177823185683*a^2 + 14343773739861044592*a + 15304161864288197145], 1] 0.12921247778342166006640932358407890233 Mod(4, 7)*x^5 + Mod(5, 7)*x^4 + Mod(2, 7)*x^3 + Mod(4, 7)*x^2 + Mod(2, 7)*x + Mod(6, 7) Total time spent: 4 pari-2.5.5/src/test/64/nf0000644000175000017500000000604412147140047013435 0ustar billbill[85997496, [42998748, 2], [[408188227, 99620635; 0, 1], [2, 1; 0, 1]]] 12.340047278667903334059769086970462116 4.1894250945222025884896456921310573060 20915648110955829231381594293324156411897455346679838307589120000 571459344155975480004612560667633185714077696 [54898, [54898], [[78513, 15567; 0, 1]]] [26, [26], [[19, 14, 18, 5; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]]] [1, [], []] *** zetakinit: Warning: non-monic polynomial. Result of the form [nf,c]. *** zetakinit: Warning: non-monic polynomial. Change of variables discarded. 20/3 -5 13 -1 1024/243 -1 31 15853839 (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]~ [7/3, 2, 3, 4, 5]~ [1/3, 0, 0, 0, 0]~ [-2, 0, 0, 0, 0]~ [2, 1, 1, 0, 0]~ [0, 2, 3, 4, 5]~ [13/3, 1, 1, 0, 0]~ [2, 1, 1, 0, 0]~ [6, 2, 2, 0, 0]~ [4, 3, 4, 4, 5]~ [7/3, 2, 3, 4, 5]~ [0, 2, 3, 4, 5]~ [4, 3, 4, 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]~ [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]~ [-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]~ [1249690/15853839, -222317/5284613, 39600/5284613, -477392/15853839, 434/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]~ [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]~ [-1, 0, 0, 0, 0]~ [1, 0, 0, 0, 0]~ [1, 0, 0, 0, 0]~ [0, 0, 0, 0, 0]~ [2, 1, 1, 0, 0]~ [-3, -1, -1, 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]~ [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]~] [[-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, 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]~] [[0, 0, 0, 0, 0]~, [3, 1, 1, 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]~] [[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/3, 0, 0, 0, 0]~ [0, 0, 0, 0, 0]~ [-4, -1, -1, 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]~ [3, 1, 1, 0, 0]~ [-1/3, -2/3, 1/3, 0, -1/3]~ [0, 0, 0, 0, 0]~ [-6, -2, 1, 2, 1]~ [0, 0, 0, 0, 0]~ [16/9, 0, 0, 0, 0]~ [-4/3, 0, 0, 0, 0]~ [4, 4/3, 4/3, 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]~ [-1, -2, -3, -4, -5]~ [4, 4/3, 4/3, 0, 0]~ [-3, -1, -1, 0, 0]~ [13, 5, 6, 2, 1]~ [-58, -42, 23, 27, 17]~ [4/3, 8/3, 4, 16/3, 20/3]~ [-1, -2, -3, -4, -5]~ [-58, -42, 23, 27, 17]~ [-1071, -384, -251, -155, 20]~ [1] Total time spent: 1864 pari-2.5.5/src/test/64/program0000644000175000017500000000743012147140047014501 0ustar billbill echo = 1 (on) ? gettime;alias(ln,log) ? ln(2) 0.69314718055994530941723212145817656808 ? 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] ? getheap [4, 31] ? getrand Vecsmall([815394335184717944, 4549279032150680234, 6773728374826070157, -237 0373754265190617, -7192197643876677099, 3146002372671609152, -37889119021821 81465, -3110751447065112512, -7839888805667742928, -1750047523337007702, -48 13916526844204946, 2197460154196732106, 2172222412836515817, 750148670758846 8027, -2859630236012475958, -7521563591744261058, -5098751749791804186, -493 2847221747616924, -83017490560352414, 909833191470153253, -68907000334182407 26, -2667729487396035417, 7945873742069551774, -8335875119100634420, -269516 2268485432158, 907840774270685481, -2649846143482627435, 4432371968824575795 , 675084127798063203, 1330710101237874403, -3282824841646116129, 66137656958 55811188, -4997019453007867026, -2517134063026061436, 6601608070123470072, 8 315730897074524817, 7382824712320294655, 8382147984209176484, 61195565499152 33413, -6473138824261887547, 3868662552751602358, -7049890781912985631, 5825 089164294808030, -747565901986682173, -3706701696228594999, 8547465356109452 89, -2464579454622871361, -6442828218203469284, 7444846227663661231, -159718 0339169755613, 1305732653808028370, 4846884492315410984, -592680480505270414 1, -5320891424889011357, -7613917326037722204, 4603012696960730681, -4168740 837400896895, 8981763047278317166, 7331246918389417837, -4002039446830895798 , 4582267480000687864, -7629613429408037667, 4813661187837882458, -776313336 5088963398, 63, 3001673639903682625]) ? getstack 200 ? 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 ? setrand(10) ? 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(realprecision,28) ? 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" "l og(p)/log(q)))); 50 1.561229126903099279206171725 100 1.601335375590875348711141031 150 1.606915548673659127523394774 200 1.618659998991528481508175176 250 1.626284706204746765086080988 300 1.627822776845103001192024532 350 1.632105905172986668189652273 400 1.632424285532931448171405619 ? install(addii,GG) ? addii(1,2) 3 ? kill(addii) ? getheap [23, 1822] ? print("Total time spent: ",gettime); Total time spent: 8 pari-2.5.5/src/test/64/linear0000644000175000017500000003662612147140047014315 0ustar billbill echo = 1 (on) ? gettime;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],-2) [Mod(6, 7), Mod(5, 7)]~ ? 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.2833494518006402717978106547571267252 1 0.283349451800640271797810654757 12672521] [-0.14167472590032013589890532737856336261 -2 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,3) [[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]) [3] ? matimagecompl(Pi*[1,3,5;2,4,6;3,5,7]) [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 840494514780771076350, 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] ? aset=Set([5,-2,7,3,5,1]) ["-2", "1", "3", "5", "7"] ? bset=Set([7,5,-5,7,2]) ["-5", "2", "5", "7"] ? setintersect(aset,bset) ["5", "7"] ? setisset([-3,5,7,7]) 0 ? setminus(aset,bset) ["-2", "1", "3"] ? setsearch(aset,3) 3 ? setsearch(bset,3) 0 ? setunion(aset,bset) ["-2", "-5", "1", "2", "3", "5", "7"] ? 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]],,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] ? getheap [104, 10299] ? print("Total time spent: ",gettime); Total time spent: 4 pari-2.5.5/CHANGES0000644000175000017500000002030412212611011012061 0ustar billbill# $Id$ Bug numbers refer to the BTS at http://pari.math.u-bordeaux.fr/Bugs/ [last column crossreferences current development release 2.6.1] Done for version 2.5.5 (released 20/09/2013): Fixed BA 1- [native kernel] FFT mulii relied on unspecified order of evaluation [2.6.0-F118] BA 2- [Configure] fix support for multiarch systems for GMP 3- local() could corrupt polynomial variable of the same name [F4] 4- Flm_Fl_mul returned a wrong result [F12] 5- allocatemem(2^36-1) --> corrupted stack [#1437] [F14] 6- stack corruption in carberkowitz / charpoly(,,3) [ session crash ] [F19] 7- subst(O(x^2),x,0*x) => SEGV [#1447] [F20] 8- bnfcertify() when primelimit < Zimmert bound => oo loop 9- dirmul/dirdiv: incorrect result length when valuation > 1 [F23] 10- x,y a t_PADIC, x === y always returned 0 [F24] 11- round((1e-40+x) / (1e-39+x)) would create the invalid object x/x [F26] 12- polgalois(x^11 + 627*x^4 - 584) -> F_110 instead of S_11 [#1460] [F27] [last column crossreferences current development release 2.6.0] Done for version 2.5.4 (released 13/05/2013): Fixed 1- sin'(1) with default(compatible,3) caused a crash [F97] 2- rare corruption in ECM [#1240] factorint(,1) => SEGV [F98] 3- add missing call to normalize() in lift(t_POL/t_SER) [#1359] [F99] BA 4- listput was not SIGINT safe [F100] BA 5- znorder(Mod(5,16),200) -> 5 instead of 4 [F101] JD 6- galoisinit(x^3+x^2-2*x-1) -> uninitialized read [#1389] [F106] BA 7- polhermite(66) -> corrupted result [#1393] [F107] 8- polred() could return non-squarefree polynomials [#1395] BA 9- galoisfixedfield() could return a wrong result for polynomials [F109] with large roots [#1406] 10- bnrdisc could return a wrong result if the modulus had more than [F110] 2 prime divisors [#1399] 11- y;z;(x^2+y)*w/z/x -> significant pointers lost [#1248] [F113] 12- thue(thueinit(x^3-1493,1),3) -> error [F115] 13- typo in modr_safe -> precision error [#1413] [F116] [last column crossreferences current development release 2.6.0] Done for version 2.5.3 (released 03/10/2012): Fixed 1- padicappr(x^2+1+O(3), -1+O(5^10)) --> no error [F34] 2- sqrtn(1+O(5),5) -> error, ispower(1+O(5),5) -> error [#1261] [F65] PB 3- printf("%.6f", 5E-5) -> SEGV [#1328] [F83] BA 4- diffop(Mod(y,x^2-y),[y],[1]) -> wrong result [F84] BA 5- calling a GP function with a lot of omitted arguments could crashes [F85] GH 6- missing solutions in thue() [#951] [F86] 7- t_RFRAC == t_RFRAC could return a wrong result [#1339] [F87] 8- obscure bug in polroots() (sage #13314) [F88] BA 9- printf() did not flush output [F90] 10- polrootsff(2*x+1,2,y) -> SEGV [#1350] [F93] BA 11- elltors() was using an insufficient precision [#1326] 12- resultant(x,x,y) -> 0 and related problems [F94] 13- thue((x^4+1)^2, 4) -> no solution [F95] BA 14- idealramgroups() and idealfrobenius() did not accept a bnf [F96] [last column crossreferences current development release 2.6.0] Done for version 2.5.2 (released 20/06/2012): Fixed 1- [from 2.5.1] substvec slowdown [F25] 2- logfile: strip properly color escape sequences [#1225] [C18] BA 3- ispower(x < 0,, &n): n could have the wrong sign [#1302] [F45] 4- mathnf(..., 4) didn't remove 0 columns from HNF [#1271] [F61] JD 5- possible SEGV in pari_init_opts [#1264] [F62] BA 6- ellorder(E,P*Mod(1,p)) did not work if E was defined over Z [F63] 7- parimacro.tex: pdftex --output-format dvi would produce a PDF [F66] BA 8- pari_close failed to free all allocated memory [#1297] [F67] 9- issquarefree(0) => error [#1304] [F71] 10- sqrt(0.E-97-1.12-97*I) -> div by 0 [#1309] [F76] PH 11- vecsort0 was not valid C code (miscompiled by gcc 4.7) BA 12- FpX_gcd(0,x) -> div by 0 [F77] 13- x; y; p; q; subst(Mod(q,p), q, x + y) --> Mod(1, p)*x [#1321] [F78] [last column crossreferences current development release 2.6.0] Done for version 2.5.1 (released 06/02/2012): Fixed 1- Euclidean chains were confused by t_POLs with t_INTMOD coeffs [F01] [ because a 0 polynomial could have lg() == 3 ] 2- remi2n didn't allow negative arguments [native kernel] [#1215] [F04] 3- qfbred(t_QFR) wrong when frac( sqrt(D) ) > 0.5 [F06] 4- problems with diagnostic messages when changing a 'default', e.g \o3[F08] 5- divru() could call bfffo(0) => overflow in expo() [F09] AMe 6- (t_FRAC<0) * t_INTMOD => wrong result [F10] 7- trace(t_POL or t_SER) could yield unormalized object [0 lead. term] [F11] LGr 8- off-by-1 error in primepi() when argument is = primelimit [F12] 9- crash when default(prettyprinter,...) points to non-existent cmd [F15] 10- qfperfection(): wrong result in unlucky cases [#1223] [F16] BA 11- allocatemem() did not reset parse error [#1226] [F17] BA 12- (x->vector(1,j,x))(1) --> significant pointers lost [#1211] [F18] VL 13- [makefile] Incorrect -I and -L flags order [#1212] [F19] 14- nfbasis / nfdisc(f,, partial factorization) would sometimes spend a [F20] lot of time trying to factorize a discriminant [#1227] BA 15- missing consistency checks in conjvec [#1231] [F22] 16- wrong result in bezoutres [#1233] [F24] 17- wrong sign in polresultant() [#1234] [F25] 18- subst(Y/X,X,x) -> 0 [F27] PB 19- polrootsff(x^2-x-ffgen((v^2+1) * Mod(1,3))) -> SEGV [#1241] [F28] BA 20- functions ending by the x[y]=z construct could corrupt the stack. [F30] BA 21- test-kernel and test-ploth did not work [F35] BA 22- for(i=1,10^7,) + SIGINT -> SEGV [#1249] [F37] BA 23- mateigen precision error was not trappable. [F40] 24- broken rnfeltup [#1256] [F42] 25- x===y was always wrong for x,y t_SER [F43] 26- ispower(x < 0) could return an even value ! [#1259] [F45] 27- ispower(1 / n) return a wrong result [#1259] [F46] BA 28- [breakloop] initial context could be lost. [F47] BA 29- Ser([1+O(x)],x) returned an invalid object. [F48] BA 30- ispseudoprime used too much stack for huge operands. [F49] 31- [rnfidealup doc] idealgentoHNF() was incorrect. [F50] DS 32- elldivpol returned wrong result for degree n >=8. [F51] 33- overflow in mpbern(n) for huge n [#1256] [F52] 34- psdraw() ignored plot colors [F55] BA 35- stack_base() was not C89 standard compliant. [F56] BA 36- my(f(x)=x+1);f --> SEGV [#1273] [F57] 37- ellheight([0, 0, 1, -1, 0], [0., 0.]) -> BUG [F58] Changed BA 1- [darwin] do not use dylib_ prefix to ld options [#1210] [C12] 2- delete README-subversion, replace with README-git [C22] 3- much faster final divisibility test in nfgcd() [#1214] [C25] Added BA 1- [INSTALL] Documentation of RUNTEST BA 2- [Configure] support for multiarch systems pari-2.5.5/doc/0000755000175000017500000000000012212611624011646 5ustar billbillpari-2.5.5/doc/tutorial.tex0000644000175000017500000047030712147140046014250 0ustar billbill% $Id$ % 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, 28 on most systems, 38 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 latter 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 28 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 the new control statements: \kbd{break}, \kbd{next}, \kbd{return}), and 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 28 decimal digits, but we may change that with \b{p} of course. \smallskip % 4) Come back to 28 digits of precision (\kbd{\b{p} 28}), and type \kbd{exp(75)}. 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 28 digits of precision, but the integer part of $\exp(24*\pi)$ has 33 decimal digits. Hence if \kbd{gp} had dutifully printed out 33 digits, the last few digits would have been wrong. Hence \kbd{gp} wants to print only 28 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 to more than 33 decimals. Let's try it. To give it a wide margin, we set the precision to 40 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 28 decimals, and even if you set the precision to 1000 decimals, \kbd{gp} knows that your number has only 28 digits of accuracy but an integral part with 33 digits. So you haven't improved things by increasing the precision. Or have you? What if we retype \kbd{exp(75)} now that we have 40 digits? Try it. Now we do not have an exponential format, and we see that at 28 decimals the last 6 digits would have been wrong if they had been printed in fixed-point 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 28, 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}. Couldn't be clearer. Taking again our universal example in precision 28, type \bprog floor(exp(75)) @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(75)} given only 28 decimals of accuracy, since it has 33 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) A complex number has a real part and an imaginary part (who would have guessed?). However, beware that when the imaginary part is the exact integer zero, it is not printed, but the complex number is not converted to a real number. Hence it may \emph{look} like a real number without being one, and this may cause some confusion in programs which expect real numbers. For example, type \kbd{n = 3 + 0*I}. The answer reads \kbd{3}, as expected. But it is still a complex number. Check it with \kbd{type(n)}. Hence if you then type \kbd{(1+x)\pow n}, instead of getting the polynomial \kbd{1 + 3*x + 3*x\pow 2 + x\pow 3} as expected, you obtain a power series. Worse, when you try to apply an arithmetic function, 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 read again if this is not clear; it is a common source of incomprehension. Similarly, \kbd{n = 3 + 0*x} is not the integer 3 but a constant polynomial equal to $3x^0$. 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 some larger value.) The reason for this is that PARI is handling real numbers with 28 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 only 2 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^{50}$, showing that some coefficients of \kbd{1/hr} are wrong by as much as $10^{24}$ (the largest error is in fact equal to $4.244 \cdot 10^{24}$ for the coefficient of row 15 and column 15, which is a 28 digit integer). To obtain the correct result after rounding for the inverse, we have to use a default precision of 56 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 two other reserved variable names: \kbd{Pi} and \kbd{Euler}. All function names are forbidden as well. On the other hand there is nothing special about \kbd{i}, \kbd{pi} or \kbd{euler}. 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. Another useful way to create vectors and matrices is to extract them from larger ones, using \kbd{vecextract}. For instance, if \kbd{h} is the $20\times 20$ Hilbert matrix as above, \bprog h = mathilbert(20); vecextract(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 never a proof. To find the factors is another story. One must use less naive techniques than trial division, or be patient. To finish this example, type \kbd{fa = factor(n)} to see the factors. The smallest factor is 14902357, we may take a small coffee break and let trial division run to completion. Type \kbd{\#} to turn the time on, then \bprog for (i = 2, ceil(sqrt(n)), if (n%i==0, print(i); break)) @eprog\noindent This takes less than one minute on a 1GHz processor. Actually, interpreting the expression in the loop takes more than two thirds of the running time as you can check by typing just \bprog for (i = 2, 14902357, n%i) @eprog\noindent 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 $10^{13}$, 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. \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{Z\_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.) 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 = vecextract( primes(10000), "-50.." ); \\ @com extract the last 50 elements 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. This is taking ages. Ah, the documentation says that \kbd{mathnf} is fast for tiny matrices but should never be used for matrices of dimension larger than $10$. Type \kbd{Control-C} to interrupt the longish computation, then \kbd{z = mathnf(H, 1);}. That's better. \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; of course it has 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 column 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, using more sophisticated algorithms like PSLQ. 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); @eprog\noindent This enumerates the vectors in $\Lambda$ which are shorter than the first LLL basis vector, at most 100 of them. 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 50840 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 32-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 28 decimals of default precision (this is what we get automatically at the start of a \kbd{gp} session on 32-bit machines). Type \kbd{e = exp(1)}. We get the number $e=2.718\dots$ to 28 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} 50}. Then type \kbd{e}, then \kbd{exp(1)} once again. This last value is the correct value of the mathematical constant $e$ to 50 decimals, while the variable \kbd{e} shows the value that was computed to 28 decimals. Clearly they coincide to exactly 29 significant digits. So 28 digits are printed, but how many significant digits are actually contained in the variable \kbd{e}? Type \kbd{\#e} which indicates we have exactly $3$ mantissa words. Since $3\ln(2^{32}) / \ln(10)\approx28.9$ we see that we have 28 or 29 significant digits (on 32-bit machines). \smallskip Come back to 28 decimals (\kbd{\b{p} 28}). If we type \kbd{exp(1.)} you can check that we also obtain 28 decimals. However, type \kbd{f = exp(1 + 1E-30)}. Although the default precision is still 28, you can check using the method above that we have in fact 59 significant digits! The reason is that \kbd{1 + 1E-30} is computed according to the PARI philosophy, i.e.~to the best possible precision. Since \kbd{1E-30} has 29 significant digits and 1 has ``infinite'' precision, the number \kbd{1 + 1E-30} will have $59=29+30$ significant digits, hence \kbd{f} also. Now type \kbd{cos(1E-15)}. 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 7 mantissa words, giving us the possibility of having 67 correct significant digits. In fact (look in precision 100), only 60 are correct. PARI gives you as much as it can, and since 6 mantissa words would have given you only 57 digits, it uses 7. 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^{-30}$ where $0.5*10^{-30}$ is considered with 28 significant digit accuracy. Hence the result will have approximately $28+30=58$ significant digits. Unfortunately, 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 (type \kbd{99!} to get the complete answer). To get the complete value, there are two solutions. The first and most natural one 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. After some work, the printed result is this time perfectly correct. However, this is probably not the best way to proceed. Come back first to the default precision (type \kbd{\b{p} 28}). As the gamma function increases very rapidly, one usually uses its logarithm. Type \kbd{lngamma(100)}. This time the result has a reasonable size, and is exactly equal to \kbd{log(99!)}. 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.)}. Although the result is the same, 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 very 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 the list of functions. In each case, 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. Come back to \kbd{\b{p} 28} since these routines are very slow when working with too many significant digits. Try \kbd{intnum(t=1,2, 1/t)} and presto! you get 26 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 zero(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 28 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 changes of variable 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: 124ms for (i=1, 10^4, sum(i = 1, 100, (i+1) * x^i) ) \\@com time: 3,985ms @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 28 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 $3.10^{-28}$, reasonable enough when we work with 28 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''). 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{ellpow} for multiplication by an integer (``powering''). For example, the negative of \kbd{q} is \kbd{ellsub(e,[0],q)}, and the double is obtained either as \kbd{ellpow(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(ellpow(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, ellpow(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(ellpow(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, vecextract(v,[1,2,3,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. There is no \kbd{nfeltnorm} function (\kbd{nfelttrace} does not exist either), but we can easily write one: \bprog nfeltnorm(nf,u) = norm(nfbasistoalg(nf, u)) @eprog\noindent Notice that this is certainly not foolproof (try it with complex or quadratic arguments!), but we could refine it if the need arose. 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're 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} is to compute an integral basis, i.e.~a $\Z$-basis of the maximal order $\Z_K$ of $K$. For a large polynomial, this implies factoring the discriminant of the polynomial, 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 (bigger than \kbd{primelimit}, whose value you can get using \kbd{default})~--- it is useless otherwise. 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 you can provide a factorization of the discriminant as an optional third argument. And here we can cheat, and give on purpose an incomplete factorization involving only the primes we want. 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,6; 1537461,1]) @eprog\noindent and the factors of 1537461 will not be looked at! (In this example it would be stupid to cheat, but if the discriminant has 2000 digits, this can be a handy trick.) 3) A last way will work if the \emph{field} discriminant is smooth (never mind the polynomial discriminant). Simply call \kbd{B = nfbasis(T, 1)}, which will return a basis for an order which is possibly not maximal. In fact, it will be maximal if the field discriminant is smooth with respect to the precomputed prime table, including \kbd{addprimes} offsprings (assuming the later are genuine primes). You may then input the resulting basis to \kbd{nfinit}, as \kbd{nfinit([T, B])}. \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 = eval( 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 28 significant digits is an obvious overkill: the output device resolution certainly won't reach $10^{28} \times 10^{28}$ 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. You probably want to use \kbd{trap} on startup as well: it enables so-called \emph{break loops} when an error occurs, 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. When break loops are enabled, \kbd{Control-C} is treated as a non-fatal error: it freezes a computation and gets you a new prompt so that you may e.g., increase debugging level, inspect or modify variables (in fact, run arbitrary commands), before letting the program go on. 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. 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.5.5/doc/usersch3.tex0000644000175000017500000205427012212162714014142 0ustar billbill% $Id$ % 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{+}, \kbd{-}: The expression $x$ \kbd{+} $y$ is the \idx{sum} and $x$ \kbd{-} $y$ is the \idx{difference} of $x$ and $y$. Addition/subtraction between a scalar type $x$ and a \typ{COL} or \typ{MAT} $y$ returns respectively $[y[1] \pm x, y[2],\dots]$ and $y \pm x \text{Id}$. Other addition/subtraction 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} for $x$ \kbd{+} $y$, \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$. \subsecidx{divrem}$(x,y,\{v\})$: \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. \subsecidx{lex}$(x,y)$: \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}. \subsecidx{max}$(x,y)$: \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}. \subsecidx{min}$(x,y)$: \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}. \subsecidx{shift}$(x,n)$: \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}. \subsecidx{shiftmul}$(x,n)$: \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}. \subsecidx{sign}$(x)$: \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}. \subsecidx{vecmax}$(x)$: \label{se:vecmax}if $x$ is a vector or a matrix, returns the maximum of the elements of $x$, otherwise returns a copy of $x$. Error if $x$ is empty. The library syntax is \fun{GEN}{vecmax}{GEN x}. \subsecidx{vecmin}$(x)$: \label{se:vecmin}if $x$ is a vector or a matrix, returns the minimum of the elements of $x$, otherwise returns a copy of $x$. Error if $x$ is empty. The library syntax 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 the following synonyms for some of the above functions: \kbd{|} and \kbd{\&} are accepted as\sidx{bitwise and}\sidx{bitwise or} synonyms of \kbd{||} and \kbd{\&\&} respectively. Also, \kbd{<>} is accepted as a synonym for \kbd{!=}. On the other hand, \kbd{=} is definitely \emph{not} a synonym for \kbd{==}: it is the assignment statement. (We do not use the customary C operators for bitwise \kbd{and} or bitwise \kbd{or}; use \tet{bitand} or \tet{bitor}.) 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. \subsecidx{Col}$(\{x=[\,]\})$: \label{se:Col} transforms the object $x$ into a column vector. 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 column vector), \item a matrix (the column of row vectors comprising the matrix is returned), \item a character string (a column of individual characters is returned), \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{Col} is the reciprocal function of \kbd{Pol} and \kbd{Ser} respectively. Note that the function \kbd{Colrev} does not exist, use \kbd{Vecrev}. The library syntax is \fun{GEN}{gtocol}{GEN x = NULL}. \subsecidx{List}$(\{x=[\,]\})$: \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. \subsecidx{Mat}$(\{x=[\,]\})$: \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}. \subsecidx{Mod}$(x,y)$: \label{se:Mod} creates the PARI object $(x \mod y)$, i.e.~an intmod or a polmod. $y$ must be an integer or a polynomial. If $y$ is an integer, $x$ must be an integer, a rational number, or a $p$-adic number compatible with the modulus $y$. If $y$ is a polynomial, $x$ must be a scalar (which is not a polmod), a polynomial, a rational function, or a power series. This function is not the same as $x$ \kbd{\%} $y$, the result of which is an integer or a polynomial. The library syntax is \fun{GEN}{gmodulo}{GEN x, GEN y}. \subsecidx{Pol}$(x,\{v=x\})$: \label{se:Pol} transforms the object $x$ into a polynomial with main variable $v$. If $x$ is a scalar, this gives a constant polynomial. If $x$ 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 $x$ is a vector: it creates the polynomial whose coefficients are given by $x$, with $x[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 x, long v = -1}, where \kbd{v} is a variable number. \subsecidx{Polrev}$(x,\{v=x\})$: \label{se:Polrev} transform the object $x$ into a polynomial with main variable $v$. If $x$ is a scalar, this gives a constant polynomial. If $x$ 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 $x$ is a vector: it creates the polynomial whose coefficients are given by $x$, with $x[1]$ being the constant term. \tet{Pol} can be used if one wants $x[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 x, long v = -1}, where \kbd{v} is a variable number. \subsecidx{Qfb}$(a,b,c,\{D=0.\})$: \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$). \subsecidx{Ser}$(s,\{v=x\},\{d=\var{seriesprecision}\})$: \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 with precision \kbd{d}. If $s$ is a polynomial, the precision is the maximum of \kbd{d} and the degree of the polynomial. 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}$(x)$), and the precision $d$ is ignored. \bprog ? Ser(x^2,, 5) %1 = x^2 + O(x^7) ? Ser([1,2,3], t) %2 = 1 + 2*t + 3*t^2 + O(t^3) @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. \subsecidx{Set}$(\{x=[\,]\})$: \label{se:Set} converts $x$ into a set, i.e.~into a row vector of character strings, with strictly increasing entries with respect to lexicographic ordering. The components of $x$ are put in canonical form (type \typ{STR}) so as to be easily sorted. To recover an ordinary \kbd{GEN} from such an element, you can apply \tet{eval} to it. Note that most set functions also accept ordinary vectors, provided their components can be compared with \kbd{<}. Sets as created by this function are only useful when e.g. polynomial or vector entries are involved. The library syntax is \fun{GEN}{gtoset}{GEN x = NULL}. \subsecidx{Str}$(\{x\}*)$: \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} \subsecidx{Strchr}$(x)$: \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}. \subsecidx{Strexpand}$(\{x\}*)$: \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} \subsecidx{Strtex}$(\{x\}*)$: \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} \subsecidx{Vec}$(\{x=[\,]\})$: \label{se:Vec} transforms the object $x$ into a row vector. That 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 matrix (the vector of columns comprising the matrix is return), \item a character string (a vector of individual characters is returned), \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. The library syntax is \fun{GEN}{gtovec}{GEN x = NULL}. \subsecidx{Vecrev}$(\{x=[\,]\})$: \label{se:Vecrev} as $\kbd{Vec}(x)$, 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}{gtovecrev}{GEN x = NULL}. \subsecidx{Vecsmall}$(\{x=[\,]\})$: \label{se:Vecsmall} transforms the object $x$ into a row vector of type \typ{VECSMALL}. This acts as \kbd{Vec}, but only on a limited set of objects (the result must be representable as a vector of small integers). In particular, polynomials and power series are forbidden. 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}{gtovecsmall}{GEN x = NULL}. \subsecidx{binary}$(x)$: \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}. \subsecidx{bitand}$(x,y)$: \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. \subsecidx{bitneg}$(x,\{n=-1\})$: \label{se:bitneg} \idx{bitwise negation} of an integer $x$, truncated to $n$ bits, 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}. \subsecidx{bitnegimply}$(x,y)$: \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. \subsecidx{bitor}$(x,y)$: \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. \subsecidx{bittest}$(x,n)$: \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. \subsecidx{bitxor}$(x,y)$: \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. \subsecidx{ceil}$(x)$: \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}. \subsecidx{centerlift}$(x,\{v\})$: \label{se:centerlift} lifts an element $x=a \bmod n$ of $\Z/n\Z$ to $a$ in $\Z$, and similarly lifts a polmod to a polynomial. This is the same as \tet{lift} except that in the particular case of elements of $\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}. \subsecidx{simplify}$(x)$: \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}. \subsecidx{sizebyte}$(x)$: \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}. \subsecidx{sizedigit}$(x)$: \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}. \subsecidx{truncate}$(x,\{\&e\})$: \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}. \subsecidx{valuation}$(x,p)$: \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}{ggval}{GEN x, GEN p}. \subsecidx{variable}$(\{x\})$: \label{se:variable} gives the main variable of the object $x$, and $p$ if $x$ is a $p$-adic number. Gives an error if $x$ has no variable associated to it. 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$. \subsecidx{Euler}: \label{se:Euler}Euler's constant $\gamma=0.57721\cdots$. Note that \kbd{Euler} is one of the few special reserved names which cannot be used for variables (the others are \kbd{I} and \kbd{Pi}, as well as all function names). The library syntax is \fun{GEN}{mpeuler}{long prec}. \subsecidx{I}: \label{se:I}the complex number $\sqrt{-1}$. The library syntax is \fun{GEN}{gen_I}{}. \subsecidx{Pi}: \label{se:Pi}the constant $\pi$ ($3.14159\cdots$). The library syntax is \fun{GEN}{mppi}{long prec}. \subsecidx{abs}$(x)$: \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}. \subsecidx{acos}$(x)$: \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}. \subsecidx{acosh}$(x)$: \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}{gach}{GEN x, long prec}. \subsecidx{agm}$(x,y)$: \label{se:agm}arithmetic-geometric mean of $x$ and $y$. In the case of complex or negative numbers, the principal square root is always chosen. $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}. \subsecidx{arg}$(x)$: \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}. \subsecidx{asin}$(x)$: \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}. \subsecidx{asinh}$(x)$: \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}{gash}{GEN x, long prec}. \subsecidx{atan}$(x)$: \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}. \subsecidx{atanh}$(x)$: \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}{gath}{GEN x, long prec}. \subsecidx{bernfrac}$(x)$: \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}. \subsecidx{bernreal}$(x)$: \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}. \subsecidx{bernvec}$(x)$: \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}. \subsecidx{besselh1}$(\var{nu},x)$: \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}. \subsecidx{besselh2}$(\var{nu},x)$: \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}. \subsecidx{besseli}$(\var{nu},x)$: \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}. \subsecidx{besselj}$(\var{nu},x)$: \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}. \subsecidx{besseljh}$(n,x)$: \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}. \subsecidx{besselk}$(\var{nu},x)$: \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}. \subsecidx{besseln}$(\var{nu},x)$: \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}. \subsecidx{cos}$(x)$: \label{se:cos}cosine of $x$. The library syntax is \fun{GEN}{gcos}{GEN x, long prec}. \subsecidx{cosh}$(x)$: \label{se:cosh}hyperbolic cosine of $x$. The library syntax is \fun{GEN}{gch}{GEN x, long prec}. \subsecidx{cotan}$(x)$: \label{se:cotan}cotangent of $x$. The library syntax is \fun{GEN}{gcotan}{GEN x, long prec}. \subsecidx{dilog}$(x)$: \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}. \subsecidx{eint1}$(x,\{n\})$: \label{se:eint1}exponential integral $\int_x^\infty \dfrac{e^{-t}}{t}\,dt$ ($x\in\R$) If $n$ is present, outputs the $n$-dimensional vector $[\kbd{eint1}(x),\dots,\kbd{eint1}(nx)]$ ($x \geq 0$). This is faster than repeatedly calling \kbd{eint1($i$ * x)}. The library syntax is \fun{GEN}{veceint1}{GEN x, GEN n = NULL, long prec}. Also available is \fun{GEN}{eint1}{GEN x, long prec}. \subsecidx{erfc}$(x)$: \label{se:erfc}complementary error function, analytic continuation of $(2/\sqrt\pi)\int_x^\infty e^{-t^2}\,dt$ ($x\in\R$). The library syntax is \fun{GEN}{gerfc}{GEN x, long prec}. \subsecidx{eta}$(z,\{\fl=0\})$: \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$). \subsecidx{exp}$(x)$: \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. \subsecidx{gamma}$(s)$: \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 $p$-adic number, 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 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. \subsecidx{polylog}$(m,x,\{\fl=0\})$: \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). \subsecidx{psi}$(x)$: \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}. \subsecidx{sin}$(x)$: \label{se:sin}sine of $x$. The library syntax is \fun{GEN}{gsin}{GEN x, long prec}. \subsecidx{sinh}$(x)$: \label{se:sinh}hyperbolic sine of $x$. The library syntax is \fun{GEN}{gsh}{GEN x, long prec}. \subsecidx{sqr}$(x)$: \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}. \subsecidx{sqrt}$(x)$: \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$ and $p$-adics are allowed as arguments. In that case, the square root (if it exists) which is returned is the one whose first $p$-adic digit is in the interval $[0,p/2]$. When the argument is an intmod a non-prime (or a non-prime-adic), 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. \subsecidx{sqrtn}$(x,n,\{\&z\})$: \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. \subsecidx{tan}$(x)$: \label{se:tan}tangent of $x$. The library syntax is \fun{GEN}{gtan}{GEN x, long prec}. \subsecidx{tanh}$(x)$: \label{se:tanh}hyperbolic tangent of $x$. The library syntax is \fun{GEN}{gth}{GEN x, long prec}. \subsecidx{teichmuller}$(x)$: \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}. \subsecidx{theta}$(q,z)$: \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}. \subsecidx{thetanullk}$(q,k)$: \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$. \subsecidx{weber}$(x,\{\fl=0\})$: \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}. \subsecidx{zeta}$(s)$: \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. \subsec{Arithmetic functions and factorization} 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.) The meaning of that optional argument is as follows and depends on its type \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 \subsecidx{addprimes}$(\{x=[\,]\})$: \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}. \subsecidx{bestappr}$(x, \{A\},\{B\})$: \label{se:bestappr}if $B$ is omitted, finds the best rational approximation to $x\in\R$ using continued fractions. If $A$ is omitted, return the best approximation affordable given the input accuracy; otherwise make sure that denominator is at most equal to $A$. If $B$ is present perform rational modular reconstruction (see below). In both cases, the function applies recursively to components of complex objects (polynomials, vectors, \dots). \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, $n/d$ is the best rational approximation to $x$ if $|d x - n| < |v x - u|$ for all integers $(u,v)$ with $v \leq A$. (Which implies that $n/d$ is a convergent of the continued fraction of $x$.) If $x$ is an \typ{INTMOD}, (or a recursive combination of those), modulo $N$ say, $B$ must be present. The routine then returns the unique rational number $a/b$ in coprime integers $a\leq A$ and $b\leq B$ which is congruent to $x$ modulo $N$. If $N \leq 2AB$, uniqueness is not guaranteed and the function fails with an error message. If rational reconstruction is not possible (no such $a/b$ exists for at least one component of $x$), returns $-1$. \bprog ? bestappr(Mod(18526731858, 11^10), 10^10, 10^10) *** at top-level: bestappr(Mod(1852673 *** ^-------------------- *** bestappr: ratlift: must have 2*amax*bmax < m, found amax=10000000000 bmax=10000000000 m=25937424601 ? bestappr(Mod(18526731858, 11^10), 10^5, 10^5) %1 = 1/7 ? bestappr(Mod(18526731858, 11^20), 10^10, 10^10) %2 = -1 @eprog\noindent In most concrete uses, $B$ is a prime power and we performed Hensel lifting to obtain $x$. If $x$ is a \typ{POLMOD}, modulo $T$ say, $B$ must be present. The routine then returns the unique rational function $P/Q$ with $\deg P\leq A$ and $\deg Q\leq B$ which is congruent to $x$ modulo $T$. If $\deg T \leq A+B$, uniqueness is not guaranteed and the function fails with an error message. If rational reconstruction is not possible, returns $-1$. The library syntax is \fun{GEN}{bestappr0}{GEN x, GEN A = NULL, GEN B = NULL}. Also available is \fun{GEN}{bestappr}{GEN x, GEN A}. \subsecidx{bezout}$(x,y)$: \label{se:bezout}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} 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 ? bezout(a,a) %2 = [0, 1, x + 0.E-28] ? bezout(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}{vecbezout}{GEN x, GEN y}. \subsecidx{bezoutres}$(x,y)$: \label{se:bezoutres}finds $u$ and $v$ such that $x*u + y*v = d$, where $d$ is the resultant of $x$ and $y$. The result is the row vector $[u,v,d]$. \sidx{extended gcd} The algorithm used (subresultant) assumes that the base ring is a domain. The library syntax is \fun{GEN}{vecbezoutres}{GEN x, GEN y}. \subsecidx{bigomega}$(x)$: \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 function accepts vector/matrices arguments, and is then applied componentwise. The library syntax is \fun{GEN}{gbigomega}{GEN x}. For a \typ{INT} $x$, the variant \fun{long}{bigomega}{GEN n} is generally easier to use. \subsecidx{binomial}$(x,y)$: \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$. \subsecidx{chinese}$(x,\{y\})$: \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. This function also allows vector and matrix arguments, in which case the operation is recursively applied to each component of the vector or matrix. For polynomial arguments, it is applied to each coefficient. 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. \subsecidx{content}$(x)$: \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}. \subsecidx{contfrac}$(x,\{b\},\{\var{nmax}\})$: \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}. \subsecidx{contfracpnqn}$(x)$: \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$. The library syntax is \fun{GEN}{pnqn}{GEN x}. \subsecidx{core}$(n,\{\fl=0\})$: \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$) \subsecidx{coredisc}$(n,\{\fl=0\})$: \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$) \subsecidx{dirdiv}$(x,y)$: \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}. \subsecidx{direuler}$(p=a,b,\var{expr},\{c\})$: \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} \subsecidx{dirmul}$(x,y)$: \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}. \subsecidx{divisors}$(x)$: \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}. \subsecidx{eulerphi}$(x)$: \label{se:eulerphi}Euler's $\phi$ (totient)\sidx{Euler totient function} function of $|x|$, in other words $|(\Z/x\Z)^*|$. Normally, $x$ must be of type integer, but the function accepts vector/matrices arguments, and is then applied componentwise. The library syntax is \fun{GEN}{geulerphi}{GEN x}. For a \typ{INT} $x$, the variant \fun{GEN}{eulerphi}{GEN n} is also available. \subsecidx{factor}$(x,\{\var{lim}\})$: \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 10^{15}$ (whose norm is $\leq 10^{15}$ 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 and satisfy $\var{lim} \leq \kbd{primelimit} + 1$; setting $\var{lim}=0$ is the same as setting it to $\kbd{primelimit} + 1$. 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 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] ? default(primelimit,10^9) time = 4,360 ms. %5 = 1000000000 ? factor(F, 10^9) \\ very slow time = 6,120 ms. %6 = [1009 1] [100003 1] [340282366920938463463374607431768211457 1] ? factorint(F, 1+8) \\ much faster, all small primes were found time = 40 ms. %7 = [1009 1] [100003 1] [340282366920938463463374607431768211457 1] ? factorint(F) \\ complete factorisation time = 260 ms. %8 = [1009 1] [100003 1] [59649589127497217 1] [5704689200685129054721 1] @eprog \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. 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 you want 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). 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 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, long lim}. The obsolete function \fun{GEN}{factor0}{GEN x, long lim} is kept for backward compatibility. \subsecidx{factorback}$(f,\{e\})$: \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}$). \subsecidx{factorcantor}$(x,p)$: \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}. \subsecidx{factorff}$(x,\{p\},\{a\})$: \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}. \subsecidx{factorial}$(x)$: \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}. \subsecidx{factorint}$(x,\{\fl=0\})$: \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}. \subsecidx{factormod}$(x,p,\{\fl=0\})$: \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}. \subsecidx{ffgen}$(P,\{v\})$: \label{se:ffgen}return the generator $g=X \pmod{P(X)}$ of the finite field defined by the polynomial $P$ (which must have \typ{INTMOD} coefficients). If \kbd{v} is given, the variable name is used to display $g$, else the variable of the polynomial $P$ is used. The library syntax is \fun{GEN}{ffgen}{GEN P, long v = -1}, where \kbd{v} is a variable number. \subsecidx{ffinit}$(p,n,\{v=x\})$: \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-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,g)}. The library syntax is \fun{GEN}{ffinit}{GEN p, long n, long v = -1}, where \kbd{v} is a variable number. \subsecidx{fflog}$(x,g,\{o\})$: \label{se:fflog}discrete logarithm of the finite field element $x$ in base $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$. It may be set as a side effect of calling \tet{ffprimroot}. If no $o$ is given, assume that $g$ is a primitive root. See \tet{znlog} for the limitations of the underlying discrete log algorithms. \bprog ? t = ffgen(ffinit(7,5)); ? o = fforder(t) %2 = 5602 \\@com \emph{not} a primitive root. ? fflog(t^10,t) %3 = 11214 \\@com Actually correct modulo o. We are lucky ! ? 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 \\ no surprise there ! ? fforder(g^10000, g, o) ? fflog(g^10000, g, o) %9 = 10000 @eprog The library syntax is \fun{GEN}{fflog}{GEN x, GEN g, GEN o = NULL}. \subsecidx{fforder}$(x,\{o\})$: \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}. \subsecidx{ffprimroot}$(x, \{\&o\})$: \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}. \subsecidx{fibonacci}$(x)$: \label{se:fibonacci}$x^{\text{th}}$ Fibonacci number. The library syntax is \fun{GEN}{fibo}{long x}. \subsecidx{gcd}$(x,\{y\})$: \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) %2 = 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{bezout}, 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}$. \subsecidx{hilbert}$(x,y,\{p\})$: \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}. \subsecidx{isfundamental}$(x)$: \label{se:isfundamental}true (1) if $x$ is equal to 1 or to the discriminant of a quadratic field, false (0) otherwise. The function accepts vector/matrices arguments, and is then applied componentwise. The library syntax is \fun{GEN}{gisfundamental}{GEN x}. \subsecidx{ispower}$(x,\{k\},\{\&n\})$: \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). \subsecidx{isprime}$(x,\{\fl=0\})$: \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}. \subsecidx{ispseudoprime}$(x,\{\fl\})$: \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}. \subsecidx{issquare}$(x,\{\&n\})$: \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 ? issquare([4, x^2], &n) %3 = [1, 1] \\ both are squares ? n %4 = [2, x] \\ the square roots @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 function accepts vector/matrices arguments, and is then applied componentwise. The library syntax is \fun{GEN}{gissquareall}{GEN x, GEN *n = NULL}. Also available is \fun{GEN}{gissquare}{GEN x}. \subsecidx{issquarefree}$(x)$: \label{se:issquarefree}true (1) if $x$ is squarefree, false (0) if not. Here $x$ can be an integer or a polynomial. The function accepts vector/matrices arguments, and is then applied componentwise. The library syntax is \fun{GEN}{gissquarefree}{GEN x}. For scalar arguments $x$ (\typ{INT} or \typ{POL}), the function \fun{long}{issquarefree}{GEN x} is easier to use. \subsecidx{kronecker}$(x,y)$: \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{GEN}{gkronecker}{GEN x, GEN y}. \subsecidx{lcm}$(x,\{y\})$: \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}. \subsecidx{moebius}$(x)$: \label{se:moebius}\idx{Moebius} $\mu$-function of $|x|$. $x$ must be of type integer. The function accepts vector/matrices arguments, and is then applied componentwise. The library syntax is \fun{GEN}{gmoebius}{GEN x}. For a \typ{INT} $x$, the variant \fun{long}{moebius}{GEN n} is generally easier to use. \subsecidx{nextprime}$(x)$: \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 function accepts vector/matrices arguments, and is then applied componentwise. The library syntax is \fun{GEN}{gnextprime}{GEN x}. For a scalar $x$, \fun{long}{nextprime}{GEN n} is also available. \subsecidx{numbpart}$(n)$: \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}. \subsecidx{numdiv}$(x)$: \label{se:numdiv}number of divisors of $|x|$. $x$ must be of type integer. The function accepts vector/matrices arguments, and is then applied componentwise. The library syntax is \fun{GEN}{gnumbdiv}{GEN x}. If $x$ is a \typ{INT}, one may use \fun{GEN}{numbdiv}{GEN n} directly. \subsecidx{omega}$(x)$: \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 function accepts vector/matrices arguments, and is then applied componentwise. The library syntax is \fun{GEN}{gomega}{GEN x}. For a \typ{INT} $x$, the variant \fun{long}{omega}{GEN n} is generally easier to use. \subsecidx{partitions}$(n,\{\var{restr}=0\})$: \label{se:partitions}returns vector of partitions of the integer $n$ (negative values return \kbd{[]}, $n = 0$ returns the trivial partition of the empty set). The second optional argument may be set to a non-negative number smaller than $n$ to restrict the value of each element in the partitions to that value. The default of 0 means that this maximum is $n$ itself. A partition is given by a \typ{VECSMALL}: \bprog ? partitions(4, 2) %1 = [Vecsmall([2, 2]), Vecsmall([1, 1, 2]), Vecsmall([1, 1, 1, 1])] @eprog\noindent correspond to $2+2$, $1+1+2$, $1+1+1+1$. The library syntax is \fun{GEN}{partitions}{long n, long restr}. \subsecidx{polrootsff}$(x,\{p\},\{a\})$: \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}. \subsecidx{precprime}$(x)$: \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 function accepts vector/matrices arguments, and is then applied componentwise. The library syntax is \fun{GEN}{gprecprime}{GEN x}. For a scalar $x$, \fun{long}{precprime}{GEN n} is also available. \subsecidx{prime}$(n)$: \label{se:prime}the $x^{\text{th}}$ prime number, which must be among the precalculated primes. The library syntax is \fun{GEN}{prime}{long n}. \subsecidx{primepi}$(x)$: \label{se:primepi}the prime counting function. Returns the number of primes $p$, $p \leq x$. Uses a naive algorithm so that $x$ must be less than \kbd{primelimit}. The library syntax is \fun{GEN}{primepi}{GEN x}. \subsecidx{primes}$(x)$: \label{se:primes}creates a row vector whose components are the first $x$ prime numbers, which must be among the precalculated primes. \bprog ? primes(10) \\ the first 10 primes %1 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] ? primes(primepi(10)) \\ the primes up to 10 %2 = [2, 3, 5, 7] @eprog The library syntax is \fun{GEN}{primes}{long x}. \subsecidx{qfbclassno}$(D,\{\fl=0\})$: \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. \subsecidx{qfbcompraw}$(x,y)$: \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 library syntax is \fun{GEN}{qfbcompraw}{GEN x, GEN y}. \subsecidx{qfbhclassno}$(x)$: \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}. \subsecidx{qfbnucomp}$(x,y,L)$: \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$. \subsecidx{qfbnupow}$(x,n)$: \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}. \subsecidx{qfbpowraw}$(x,n)$: \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}. \subsecidx{qfbprimeform}$(x,p)$: \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}. \subsecidx{qfbred}$(x,\{\fl=0\},\{d\},\{\var{isd}\},\{\var{sd}\})$: \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)}). \subsecidx{qfbsolve}$(Q,p)$: \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}. \subsecidx{quadclassunit}$(D,\{\fl=0\},\{\var{tech}=[\,]\})$: \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 positive 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 = 0.2$ means that relations are easier to find, but more relations are needed and the linear algebra will be harder. 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} \subsecidx{quaddisc}$(x)$: \label{se:quaddisc}discriminant of the quadratic field $\Q(\sqrt{x})$, where $x\in\Q$. The library syntax is \fun{GEN}{quaddisc}{GEN x}. \subsecidx{quadgen}$(D)$: \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}. \subsecidx{quadhilbert}$(D)$: \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}. \subsecidx{quadpoly}$(D,\{v=x\})$: \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. \subsecidx{quadray}$(D,f)$: \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}. \subsecidx{quadregulator}$(x)$: \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}. \subsecidx{quadunit}$(D)$: \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}. \subsecidx{removeprimes}$(\{x=[\,]\})$: \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}. \subsecidx{sigma}$(x,\{k=1\})$: \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 function accepts vector/matrices arguments for $x$, and is then applied componentwise. The library syntax is \fun{GEN}{gsumdivk}{GEN x, long k}. Also available are \fun{GEN}{gsumdiv}{GEN n} ($k = 1$), \fun{GEN}{sumdivk}{GEN n,long k} ($n$ a \typ{INT}) and \fun{GEN}{sumdiv}{GEN n} ($k = 1$, $n$ a \typ{INT}) \subsecidx{sqrtint}$(x)$: \label{se:sqrtint}integer square root of $x$, which must be a non-negative integer. The result is non-negative and rounded towards zero. The library syntax is \fun{GEN}{sqrtint}{GEN x}. \subsecidx{stirling}$(n,k,\{\fl=1\})$: \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]; 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$). \subsecidx{sumdedekind}$(h,k)$: \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}. \subsecidx{zncoppersmith}$(P, N, X, \{B=N\})$: \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 p = nextprime(random(10^30)); q = nextprime(random(10^30)); N = p*q; p0 = p % 10^20; \\ assume we know 1) p > 10^29, 2) the last 19 digits of p p1 = zncoppersmith(10^19*x + p0, N, 10^12, 10^29) \\ result in 10ms. %1 = [35023733690] ? gcd(p1[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 3.8s. %3 = [265174753892462432] ? %[1] == x0 %4 = 1 @eprog\noindent We guessed an integer of the order of $10^{18}$ in a couple of seconds. The library syntax is \fun{GEN}{zncoppersmith}{GEN P, GEN N, GEN X, GEN B = NULL}. \subsecidx{znlog}$(x,g,\{o\})$: \label{se:znlog}discrete logarithm of $x$ in $(\Z/N\Z)^*$ in base $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$. If no $o$ is given, assume that $g$ generate $(\Z/N\Z)^*$. This function uses a simple-minded combination of generic discrete log algorithms (index calculus methods are not yet implemented). \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$ small), \item Pollard rho method ($q$ large). 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. \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 @eprog\noindent The result is undefined when $x$ is not a power of $g$ or when $x$ is not invertible mod $N$: \bprog ? znlog(6, Mod(2,3)) *** at top-level: znlog(6,Mod(2,3)) *** ^----------------- *** znlog: impossible inverse modulo: Mod(0, 3). @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}. \subsecidx{znorder}$(x,\{o\})$: \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}. \subsecidx{znprimroot}$(n)$: \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, then the smallest positive primitive root is returned. This is no longer true for composites. 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 very costly if $p$ is large. The function accepts vector/matrices arguments, and is then applied componentwise. The library syntax is \fun{GEN}{znprimroot0}{GEN n}. For a \typ{INT} $x$, the special case \fun{GEN}{znprimroot}{GEN n} is also available. \subsecidx{znstar}$(n)$: \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$. The library syntax is \fun{GEN}{znstar}{GEN n}. %SECTION: number_theoretical \section{Functions related to elliptic curves} We have implemented a number of functions which are useful for number theorists working on elliptic curves. We always use \idx{Tate}'s notations. The functions assume that the curve is given by a general Weierstrass model\sidx{Weierstrass equation} $$ y^2+a_1xy+a_3y=x^3+a_2x^2+a_4x+a_6, $$ where a priori the $a_i$ can be of any scalar type. This curve can be considered as a five-component vector \kbd{E=[a1,a2,a3,a4,a6]}. Points on \kbd{E} are represented as two-component vectors \kbd{[x,y]}, except for the point at infinity, i.e.~the identity element of the group law, represented by the one-component vector \kbd{[0]}. It is useful to have at one's disposal more information. This is given by the function \tet{ellinit}, which initializes and returns an \tev{ell} structure by default. If a specific flag is added, a shortened \tev{smallell} is returned, which is much faster to compute but contains less information. The following \idx{member functions} are available to deal with the output of \kbd{ellinit}, both \var{ell} and \var{smallell}: \settabs\+xxxxxxxxxxxxxxxxxx&: &\cr \+ \kbd{a1}--\kbd{a6}, \kbd{b2}--\kbd{b8}, \kbd{c4}--\kbd{c6} &: & coefficients of the elliptic curve.\cr \+ \tet{area} &: & volume of the complex lattice defining $E$.\cr \+ \tet{disc} &: & discriminant of the curve.\cr \+ \tet{j} &: & $j$-invariant of the curve.\cr \+ \tet{omega}&: & $[\omega_1,\omega_2]$, periods forming a basis of the complex lattice defining $E$ ($\omega_1$ is the\cr \+ & & real period, and $\omega_1/\omega_2$ belongs to Poincar\'e's half-plane).\cr \+ \tet{eta} &: & quasi-periods $[\eta_1, \eta_2]$, such that $\eta_1\omega_2-\eta_2\omega_1=2i\pi$.\cr \+ \tet{roots}&: & roots of the associated Weierstrass equation.\cr \+ \tet{tate} &: & $[u^2,u,v]$ in the notation of Tate.\cr \+ \tet{w} &: & Mestre's $w$ (this is technical).\cr \noindent {\bf 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.) The member functions \kbd{area}, \kbd{eta} and \kbd{omega} are only available for curves over $\Q$. Conversely, \kbd{tate} and \kbd{w} are only available for curves defined over $\Q_p$. The use of member functions is best described by an example: \bprog ? E = ellinit([0,0,0,0,1]); \\@com The curve $y^2 = x^3 + 1$ ? E.a6 %2 = 1 ? E.c6 %3 = -864 ? E.disc %4 = -432 @eprog \smallskip Some functions, in particular those relative to height computations (see \kbd{ellheight}) require also that the curve be in minimal Weierstrass form, which is duly stressed in their description below. This is achieved by the function \kbd{ellminimalmodel}. \emph{Using a non-minimal model in such a routine will yield a wrong result!} All functions related to elliptic curves share the prefix \kbd{ell}, and the precise curve we are interested in is always the first argument, in either one of the three formats discussed above, unless otherwise specified. The requirements are given as the \emph{minimal} ones: any richer structure may replace the ones requested. For instance, in functions which have no use for the extra information given by an \tev{ell} structure, the curve can be given either as a five-component vector, as a \var{smallell}, or as an \var{ell}; if a \var{smallell} is requested, an \var{ell} may equally be given. 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. The function \tet{ellinit} will also 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. \subsecidx{ellL1}$(e, r)$: \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}. \subsecidx{elladd}$(E,\var{z1},\var{z2})$: \label{se:elladd} sum of the points $z1$ and $z2$ on the elliptic curve corresponding to $E$. The library syntax is \fun{GEN}{addell}{GEN E, GEN z1, GEN z2}. \subsecidx{ellak}$(E,n)$: \label{se:ellak} computes the coefficient $a_n$ of the $L$-function of the elliptic curve $E$, i.e.~in principle coefficients of a newform of weight 2 assuming \idx{Taniyama-Weil conjecture} (which is now known to hold in full generality thanks to the work of \idx{Breuil}, \idx{Conrad}, \idx{Diamond}, \idx{Taylor} and \idx{Wiles}). $E$ must be a \var{smallell} as output by \kbd{ellinit}. For this function to work for every $n$ and not just those prime to the conductor, $E$ must be a minimal Weierstrass equation. If this is not the case, use the function \kbd{ellminimalmodel} before using \kbd{ellak}. The library syntax is \fun{GEN}{akell}{GEN E, GEN n}. \subsecidx{ellan}$(E,n)$: \label{se:ellan} computes the vector of the first $n$ $a_k$ corresponding to the elliptic curve $E$. All comments in \kbd{ellak} description remain valid. The library syntax is \fun{GEN}{anell}{GEN E, long n}. \subsecidx{ellanalyticrank}$(e, \{\var{eps}\})$: \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}. \subsecidx{ellap}$(E,\{p\})$: \label{se:ellap}computes the trace of Frobenius $a_p$ for the elliptic curve $E$ and the prime number $p$. This is defined by the equation $\#E(\F_p) = p+1 - a_p$, where $\#E(\F_p)$ stands for the number of points of the curve $E$ over the finite field $\F_p$. No checking is done that $p$ is indeed prime. $E$ must be a \var{smallell} as output by \kbd{ellinit}, defined over $\Q$, $\Q_p$, or $\F_p$. The prime $p$ may be omitted if the curve was defined over $\F_p$ (\typ{INTMOD} coefficients) or $\Q_p$ (\typ{PADIC} coefficients). Otherwise the curve must be defined over $\Q$, and $p$ must be explicitly given. Over $\Q$ or $\Q_p$, the equation is assumed to be minimal at $p$. \bprog ? E = ellinit([0,0,0,0,1]); \\ defined over Q ? ellap(E, 3) \\ 3 necessary here %2 = 0 \\ #E(F_3) = 3+1 - 0 = 4 ? ellap(E, 7) %3 = -4 \\ #E(F_7) = 12 ? E = ellinit([0,0,0,0,1] * Mod(1,11)); \\ defined over F_11 ? ellap(E) \\ no need to repeat 11 %5 = 0 ? ellap(E, 11) \\ ... but it also works %6 = 0 ? ellgroup(E, 13) \\ ouch, inconsistent input ! *** at top-level: ellap(E,13) *** ^----------- *** ellap: inconsistent moduli in Rg_to_Fp: 11, 13. @eprog \misctitle{Algorithms used} If $E/\F_p$ has CM by a principal imaginary quadratic order we use an explicit formula (involving essentially Kronecker symbols and Cornacchia's algorithm, hence very fast: $O(\log p)^2$). Otherwise, we use Shanks-Mestre's baby-step/giant-step method, which runs in time $O(p^{1/4})$ using $O(p^{1/4})$ storage, hence becomes unreasonable when $p$ has about 30~digits. If the \tet{seadata} package is installed, the \tet{SEA} algorithm becomes available and primes of the order of 200~digits become feasible. The library syntax is \fun{GEN}{ellap}{GEN E, GEN p = NULL}. \subsecidx{ellbil}$(E,\var{z1},\var{z2})$: \label{se:ellbil} if $z1$ and $z2$ are points on the elliptic curve $E$, assumed to be integral given by a minimal model, 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}. \subsecidx{ellchangecurve}$(E,v)$: \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 a \var{smallell} as output by \kbd{ellinit}. The library syntax is \fun{GEN}{ellchangecurve}{GEN E, GEN v}. \subsecidx{ellchangepoint}$(x,v)$: \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}). 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. \subsecidx{ellconvertname}$(\var{name})$: \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}. \subsecidx{elldivpol}$(E,n,\{v='x\})$: \label{se:elldivpol}$n$-division polynomial for the curve \kbd{E} in the variable $v$. The library syntax is \fun{GEN}{elldivpol}{GEN E, long n, long v = -1}, where \kbd{v} is a variable number. \subsecidx{elleisnum}$(E,k,\{\fl=0\})$: \label{se:elleisnum} $E$ being an elliptic curve as output by \kbd{ellinit} (or, alternatively, given by a 2-component vector $[\omega_1,\omega_2]$ representing its periods), and $k$ being an even positive integer, computes the numerical value of the Eisenstein series of weight $k$ at $E$, 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. 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 E, long k, long flag, long prec}. \subsecidx{elleta}$(\var{om})$: \label{se:elleta} returns the quasi-periods $[\eta_1,\eta_2]$ associated to the lattice basis $\var{om} = [\omega_1, \omega_2]$. Alternatively, \var{om} 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 om, long prec}. \subsecidx{ellgenerators}$(E)$: \label{se:ellgenerators} returns a $\Z$-basis of the free part of the \idx{Mordell-Weil group} associated to $E$. This function depends on the \tet{elldata} database being installed and referencing the curve, and so is only available for curves over $\Z$ of small conductors. The library syntax is \fun{GEN}{ellgenerators}{GEN E}. \subsecidx{ellglobalred}$(E)$: \label{se:ellglobalred} calculates the arithmetic conductor, the global minimal model of $E$ and the global \idx{Tamagawa number} $c$. $E$ must be a \var{smallell} as output by \kbd{ellinit}, \emph{and is supposed to have all its coefficients $a_i$ in} $\Q$. The result is a 3 component vector $[N,v,c]$. $N$ is the arithmetic conductor of the curve. $v$ gives the coordinate change for $E$ over $\Q$ to the minimal integral model (see \tet{ellminimalmodel}). Finally $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} The library syntax is \fun{GEN}{ellglobalred}{GEN E}. \subsecidx{ellgroup}$(E,\{p\})$: \label{se:ellgroup}computes the structure of the group $E(\F_p) \sim \Z/d_1\Z \times \Z/d_2\Z$, with $d_2\mid d_1$. The prime $p$ may be omitted if the curve was defined over $\F_p$ (\typ{INTMOD} coefficients) or $\Q_p$ (\typ{PADIC} coefficients). Otherwise the curve must be defined over $\Q$, and $p$ must be explicitly given. Over $\Q$ or $\Q_p$, the equation is assumed to be minimal at $p$. \bprog ? E = ellinit([0,0,0,0,1]); \\ defined over Q ? ellgroup(E, 3) \\ 3 necessary here %2 = [4] \\ cyclic ? ellgroup(E, 7) %3 = [6, 2] \\ non-cyclic ? E = ellinit([0,0,0,0,1] * Mod(1,11)); \\ defined over F_11 ? ellgroup(E) \\ no need to repeat 11 %5 = [12] ? ellgroup(E, 11) \\ ... but it also works %6 = [12] ? ellgroup(E, 13) \\ ouch, inconsistent input ! *** at top-level: ellgroup(E,13) *** ^-------------- *** ellgroup: inconsistent moduli in Rg_to_Fp: 11, 13. @eprog The library syntax is \fun{GEN}{ellgroup}{GEN E, GEN p = NULL}. \subsecidx{ellheight}$(E,x,\{\fl=2\})$: \label{se:ellheight}global \idx{N\'eron-Tate height} of the point $z$ on the elliptic curve $E$ (defined over $\Q$), given by a standard minimal integral model. $E$ must be an \kbd{ell} as output by \kbd{ellinit}. \fl selects the algorithm used to compute the Archimedean local height. If $\fl=0$, this computation is done using sigma and theta-functions and a trick due to J.~Silverman. If $\fl=1$, use Tate's $4^n$ algorithm. If $\fl=2$, use Mestre's AGM algorithm. The latter is much faster than the other two, both in theory (converges quadratically) and in practice. 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$). \subsecidx{ellheightmatrix}$(E,x)$: \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 that this matrix should be divided by 2 to be in accordance with certain normalizations. $E$ is assumed to be integral, given by a minimal model. The library syntax is \fun{GEN}{mathell}{GEN E, GEN x, long prec}. \subsecidx{ellidentify}$(E)$: \label{se:ellidentify} look up the elliptic curve $E$ (over $\Z$) in the \tet{elldata} database and return \kbd{[[N, M, G], C]} where $N$ is the name of the curve in the J.~E.~Cremona database, $M$ the minimal model, $G$ a $\Z$-basis of the free part of the \idx{Mordell-Weil group} of $E$ and $C$ the coordinates change (see \kbd{ellchangecurve}). The library syntax is \fun{GEN}{ellidentify}{GEN E}. \subsecidx{ellinit}$(x,\{\fl=0\})$: \label{se:ellinit} initialize an \tet{ell} structure, associated to the elliptic curve $E$. $E$ is either 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 $$ or a string, in this case the coefficients of the curve with matching name are looked in the \tet{elldata} database if available. \bprog ? E = ellinit([0,0,0,0,1]); \\ y^2 = x^3 + 1 ? E = ellinit("36a1"); \\ the same curve, using Cremona's notations @eprog\noindent For the time being, only curves over a prime field $\F_p$ and over the $p$-adic or real numbers (including rational numbers) are fully supported. Other domains are only supported for very basic operations such as point addition. The result of \tet{ellinit} is an \tev{ell} structure by default, and a shorter \tev{sell} if $\fl=1$. Both contain the following information in their 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}. The other six components are only present if $\fl$ is $0$ or omitted, in which case the computation will be 10 ($p$-adic) to 200 (complex) times slower. Their content depends on whether the curve is defined over $\R$ or not: \smallskip \item When $E$ is defined over $\R$, \kbd{$E$.roots} is a vector whose three components contain the roots of the right hand side of the associated Weierstrass equation. $$ (y + a_1x/2 + a_3/2)^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. Then $\omega_1 = $\kbd{$E$.omega[1]} is the real period of $E$ (integral of $dx/(2y+a_1x+a_3)$ over the connected component of the identity element of the real points of the curve), and $\omega_2 = $\kbd{$E$.omega[2]} is a complex period. \kbd{$E$.omega} forms a basis of the complex lattice defining $E$, such that $\tau=\dfrac{\omega_1}{\omega_2}$ has positive imaginary part. \kbd{$E$.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$. Finally, \kbd{$E$.area} is the volume of the complex lattice defining $E$.\smallskip \item When $E$ is defined over $\Q_p$, the $p$-adic valuation of $j$ must be negative. Then \kbd{$E$.roots} is the vector with a single component equal to the $p$-adic root of the associated Weierstrass equation corresponding to $-1$ under the Tate parametrization. \kbd{$E$.tate} yields the three-component vector $[u^2,u,q]$, in the notations of Tate. If the $u$-component does not belong to $\Q_p$, it is set to zero. \kbd{$E$.w} is Mestre's $w$ (this is technical). \smallskip For all other base fields or rings, the last six components are arbitrarily set to zero. See also the description of member functions related to elliptic curves at the beginning of this section. The library syntax is \fun{GEN}{ellinit0}{GEN x, long flag, long prec}. Also available are \fun{GEN}{ellinit}{GEN E, long prec} ($\fl=0$) and \fun{GEN}{smallellinit}{GEN E, long prec} ($\fl=1$). \subsecidx{ellisoncurve}$(E,z)$: \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. \subsecidx{ellj}$(x)$: \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}. \subsecidx{elllocalred}$(E,p)$: \label{se:elllocalred} calculates the \idx{Kodaira} type of the local fiber of the elliptic curve $E$ at the prime $p$. $E$ must be a \var{smallell} 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. Normally, this has no use if $u$ is 1, that is, if the given equation was already minimal. Finally, the last component $c$ is the local \idx{Tamagawa number} $c_p$. The library syntax is \fun{GEN}{elllocalred}{GEN E, GEN p}. \subsecidx{elllog}$(E,P,G,\{o\})$: \label{se:elllog}discrete logarithm of the point $P$ of the elliptic curve $E$ in base $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 = ellpow(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 ? ellpow(E,G,e) == P %6 = 1 @eprog The library syntax is \fun{GEN}{elllog}{GEN E, GEN P, GEN G, GEN o = NULL}. \subsecidx{elllseries}$(E,s,\{A=1\})$: \label{se:elllseries} $E$ being an \var{sell} as output by \kbd{ellinit}, this computes the value of the L-series of $E$ at $s$. It is assumed that $E$ is defined over $\Q$, not necessarily minimal. The optional parameter $A$ is a cutoff point for the integral, which must be chosen close to 1 for best speed. The result must be independent of $A$, so this allows some internal checking of the function. Note that if the conductor of the curve is large, say greater than $10^{12}$, this function will take an unreasonable amount of time since it uses an $O(N^{1/2})$ algorithm. The library syntax is \fun{GEN}{elllseries}{GEN E, GEN s, GEN A = NULL, long prec}. \subsecidx{ellminimalmodel}$(E,\{\&v\})$: \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}. \subsecidx{ellmodulareqn}$(l,\{x\},\{y\})$: \label{se:ellmodulareqn}return a vector [\kbd{eqn},$t$] where \kbd{eqn} is a modular equation of level $l$, for $l<500$, $l$ prime. This requires the package seadata to be installed. The equation is either of canonical type ($t=0$) or of Atkin type ($t=1$). The library syntax is \fun{GEN}{ellmodulareqn}{long l, long x = -1, long y = -1}, where \kbd{x}, \kbd{y} are variable numbers. \subsecidx{ellorder}$(E,z,\{o\})$: \label{se:ellorder} gives the order of the point $z$ on the elliptic curve $E$. If the curve is defined over $\Q$, return zero if the point has infinite order. The parameter $o$, if present, 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. For a curve defined over $\F_p$, it is very important to supply $o$ since its computation is very expensive and should only be done once, using \bprog ? N = p+1-ellap(E,p); o = [N, factor(N)]; @eprog\noindent possibly using the \tet{seadata} package; for a curve defined over a non-prime finite field, giving the order is \emph{mandatory} since no function is available yet to compute the cardinality or trace of Frobenius in that case. 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. \subsecidx{ellordinate}$(E,x)$: \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}. \subsecidx{ellpointtoz}$(E,P)$: \label{se:ellpointtoz} if $E$ is an elliptic curve with coefficients in $\R$, this computes a complex number $t$ (modulo the lattice defining $E$) corresponding to the point $z$, i.e.~such that, in the standard Weierstrass model, $\wp(t)=z[1],\wp'(t)=z[2]$. In other words, this is the inverse function of \kbd{ellztopoint}. More precisely, if $(w1,w2)$ are the real and complex periods of $E$, $t$ is such that $0 \leq \Re(t) < w1$ and $0 \leq \Im(t) < \Im(w2)$. If $E$ has coefficients in $\Q_p$, then either Tate's $u$ is in $\Q_p$, in which case the output is a $p$-adic number $t$ corresponding to the point $z$ under the Tate parametrization, or only its square is, in which case the output is $t+1/t$. $E$ must be an \var{ell} as output by \kbd{ellinit}. The library syntax is \fun{GEN}{zell}{GEN E, GEN P, long prec}. \subsecidx{ellpow}$(E,z,n)$: \label{se:ellpow} 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([0,0,0,1,0]); z = [0,0]; ? ellpow(Ei, z, 10) %2 = [0] \\ unsurprising: z has order 2 ? ellpow(Ei, z, I) %3 = [0, 0] \\ Ei has complex multiplication by Z[i] ? ellpow(Ei, z, quadgen(-4)) %4 = [0, 0] \\ an alternative syntax for the same query ? Ej = ellinit([0,0,0,0,1]); z = [-1,0]; ? ellpow(Ej, z, I) *** at top-level: ellpow(Ej,z,I) *** ^-------------- *** ellpow: not a complex multiplication in powell. ? ellpow(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}{powell}{GEN E, GEN z, GEN n}. \subsecidx{ellrootno}$(E,\{p=1\})$: \label{se:ellrootno} $E$ being a \var{smallell} as output by \kbd{ellinit}, this computes the local (if $p\neq 1$) or global (if $p=1$) root number of the L-series of the elliptic curve $E$. 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$ must have coefficients in $\Q$ but need \emph{not} be minimal. The library syntax is \fun{long}{ellrootno}{GEN E, GEN p = NULL}. \subsecidx{ellsearch}$(N)$: \label{se:ellsearch}if $N$ is an integer, it is taken as a conductor else if $N$ is a string, it can be a curve name ("11a1"), an isogeny class ("11a") or a conductor "11". This function finds all curves in the \tet{elldata} database with the given property. If $N$ is a full curve name, 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. If $N$ is not a full-curve name, the output is a vector of all matching curves in the above format. The library syntax is \fun{GEN}{ellsearch}{GEN N}. Also available is \fun{GEN}{ellsearchcurve}{GEN N} that only accepts complete curve names. \subsecidx{ellsigma}$(E,z,\{\fl=0\})$: \label{se:ellsigma} $E$ being given by \kbd{ellinit}, returns the value at $z$ of the Weierstrass $\sigma$ function of the period lattice $L$ of $E$: $$ \sigma(z, L) = z \prod_{\omega\in L^*} \left(1 - \dfrac{z}{\omega}\right)e^{\dfrac{z}{\omega} + \dfrac{z^2}{2\omega^2}}$$ Alternatively, one can input a lattice basis $[\omega_1,\omega_2]$ directly instead of $E$. If $\fl=1$, computes an (arbitrary) determination of $\log(\sigma(z))$. If $\fl=2,3$, same using the product expansion instead of theta series. The library syntax is \fun{GEN}{ellsigma}{GEN E, GEN z, long flag, long prec}. \subsecidx{ellsub}$(E,\var{z1},\var{z2})$: \label{se:ellsub} difference of the points $z1$ and $z2$ on the elliptic curve corresponding to $E$. The library syntax is \fun{GEN}{subell}{GEN E, GEN z1, GEN z2}. \subsecidx{elltaniyama}$(E, \{d = \var{seriesprecision}\})$: \label{se:elltaniyama} computes the modular parametrization of the elliptic curve $E$, where $E$ is a \var{smallell} as output by \kbd{ellinit}, in the form of a two-component vector $[u,v]$ of power series, given to $d$ significant terms (\tet{seriesprecision} by default). This vector is characterized by the following two properties. First the point $(x,y)=(u,v)$ satisfies the equation of the elliptic curve. Second, the differential $du/(2v+a_1u+a_3)$ is equal to $f(z)dz$, a differential form on $H/\Gamma_0(N)$ where $N$ is the conductor of the curve. 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)$. It is assumed that the curve is a \emph{strong} \idx{Weil curve}, and that the Manin constant is equal to 1. The equation of the curve $E$ must be minimal (use \kbd{ellminimalmodel} to get a minimal equation). The library syntax is \fun{GEN}{elltaniyama}{GEN E, long precdl}. \subsecidx{elltatepairing}$(E, P, Q, m)$: \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}. \subsecidx{elltors}$(E,\{\fl=0\})$: \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} as output by \kbd{ellinit}. \bprog ? E = ellinit([0,0,0,-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$, use Doud's algorithm: bound torsion by computing $\#E(\F_p)$ for small primes of good reduction, then look for torsion points using Weierstrass parametrization (and Mazur's classification). If $\fl = 1$, use Lutz-Nagell (\emph{much} slower), $E$ is allowed to be a \var{smallell}. The library syntax is \fun{GEN}{elltors0}{GEN E, long flag}. Also available is \fun{GEN}{elltors}{GEN E} for \kbd{elltors(E, 0)}. \subsecidx{ellweilpairing}$(E, P, Q, m)$: \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}. \subsecidx{ellwp}$(E,\{z=x\},\{\fl=0\},\{d=\var{seriesprecision}\})$: \label{se:ellwp}Computes the value at $z$ of the Weierstrass $\wp$ function attached to the elliptic curve $E$ as given by \kbd{ellinit} (alternatively, $E$ can be given as a lattice $[\omega_1,\omega_2]$). If $z$ is omitted or is a simple variable, computes the \emph{power series} expansion in $z$ (starting $z^{-2}+O(z^2)$). The series is given to $d$ significant terms (\tet{seriesprecision} by default). Optional \fl\ is (for now) only taken into account when $z$ is numeric, and means 0: compute only $\wp(z)$, 1: compute $[\wp(z),\wp'(z)]$. The library syntax is \fun{GEN}{ellwp0}{GEN E, GEN z = NULL, long flag, long precdl, long prec}. Also available is \fun{GEN}{weipell}{GEN E, long precdl} for the power series. \subsecidx{ellzeta}$(E,z)$: \label{se:ellzeta} $E$ being given by \kbd{ellinit}, returns the value at $z$ of the Weierstrass $\zeta$ function of the period lattice $L$ of $E$: $$ \zeta(z, L) = \dfrac{1}{z} + z^2\sum_{\omega\in L^*} \dfrac{1}{\omega^2(z-\omega)}.$$ Alternatively, one can input a lattice basis $[\omega_1,\omega_2]$ directly instead of $E$. \bprog ? e = ellinit([0,0,0,1,0]); ? ellzeta(e, e.omega[1]/2) %2 = 0.8472130847939790866064991234 + 4.417621070 E-29*I ? 2*ellzeta([1,I], 1/2) %3 = 3.141592653589793238462643384 + 0.E-37*I @eprog\noindent 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 directly as $\eta_i = 2\zeta(\omega_i/2)$ or using \tet{elleta}. The library syntax is \fun{GEN}{ellzeta}{GEN E, GEN z, long prec}. \subsecidx{ellztopoint}$(E,z)$: \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, $[x,y]$ represents the \idx{Weierstrass $\wp$-function} and its derivative. 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}. %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 positive real numbers. 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.3$. $\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 \subsecidx{bnfcertify}$(\var{bnf},\{\fl = 0\})$: \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. If flag is present, only certify that the class group is a quotient of the one computed in bnf (much simpler in general). The library syntax is \fun{long}{bnfcertify0}{GEN bnf, long flag }. Also available is \fun{GEN}{bnfcertify}{GEN bnf} ($\fl=0$). \subsecidx{bnfcompress}$(\var{bnf})$: \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}. \subsecidx{bnfdecodemodule}$(\var{nf},m)$: \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. The library syntax is \fun{GEN}{decodemodule}{GEN nf, GEN m}. \subsecidx{bnfinit}$(P,\{\fl=0\},\{\var{tech}=[\,]\})$: \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. \subsecidx{bnfisintnorm}$(\var{bnf},x)$: \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}. \subsecidx{bnfisnorm}$(\var{bnf},x,\{\fl=1\})$: \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}. \subsecidx{bnfisprincipal}$(\var{bnf},x,\{\fl=1\})$: \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). \subsecidx{bnfissunit}$(\var{bnf},\var{sfu},x)$: \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}. \subsecidx{bnfisunit}$(\var{bnf},x)$: \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}. \subsecidx{bnfnarrow}$(\var{bnf})$: \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}. \subsecidx{bnfsignunit}$(\var{bnf})$: \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}. \subsecidx{bnfsunit}$(\var{bnf},S)$: \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}. \subsecidx{bnrL1}$(\var{bnr}, \{\var{subgrp}\}, \{\fl=0\})$: \label{se:bnrL1}\var{bnr} being the number field data which is output by \kbd{bnrinit(,,1)} and \var{subgrp} being a square matrix defining a congruence subgroup of the ray class group corresponding to \var{bnr} (the trivial congruence subgroup if omitted), returns for each \idx{character} $\chi$ of the ray class group which is trivial on this subgroup, 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 character $\chi$ a vector $[r_\chi , c_\chi]$ where $r_\chi$ is the order of $L(s, \chi)$ at $s = 0$ and $c_\chi$ the first non-zero term in the expansion of $L(s, \chi)$ at $s = 0$; in other words % $$L(s, \chi) = c_\chi \cdot s^{r_\chi} + O(s^{r_\chi + 1})$$ % \noindent near $0$. \fl\ is optional, default value is 0; its binary digits mean 1: compute at $s = 1$ if set to 1 or $s = 0$ if set to 0, 2: compute the primitive $L$-functions associated to $\chi$ if set to 0 or the $L$-function with Euler factors at prime ideals dividing the modulus of \var{bnr} removed if set to 1 (this is the so-called $L_S(s, \chi)$ function where $S$ is the set of infinite places of the number field together with the finite prime ideals dividing the modulus of \var{bnr}, see the example below), 3: returns also the character. Example: \bprog bnf = bnfinit(x^2 - 229); bnr = bnrinit(bnf,1,1); bnrL1(bnr) @eprog\noindent returns the order and the first non-zero term of the abelian $L$-functions $L(s, \chi)$ at $s = 0$ where $\chi$ runs through the characters of the class group of $\Q(\sqrt{229})$. Then \bprog bnr2 = bnrinit(bnf,2,1); bnrL1(bnr2,,2) @eprog\noindent returns the order and the first non-zero terms of the abelian $L$-functions $L_S(s, \chi)$ at $s = 0$ where $\chi$ runs through the characters of the class group of $\Q(\sqrt{229})$ and $S$ is the set of infinite places of $\Q(\sqrt{229})$ 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 exactly the same answer as \kbd{bnrL1(bnr,0)}. The library syntax is \fun{GEN}{bnrL1}{GEN bnr, GEN subgrp = NULL, long flag, long prec}. \subsecidx{bnrclassno}$(\var{bnf},I)$: \label{se:bnrclassno}$\var{bnf}$ being as output by \kbd{bnfinit} (units are mandatory unless the ideal is trivial), and $I$ being a modulus, computes the ray class number of the number field for the modulus $I$. One can input the associated \var{bid} for $I$ 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}{bnrclassno}{GEN bnf, GEN I}. \subsecidx{bnrclassnolist}$(\var{bnf},\var{list})$: \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}. \subsecidx{bnrconductor}$(A,\{B\},\{C\},\{\fl=0\})$: \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} \subsecidx{bnrconductorofchar}$(\var{bnr},\var{chi})$: \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}. \subsecidx{bnrdisc}$(A,\{B\},\{C\},\{\fl=0\})$: \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}. \subsecidx{bnrdisclist}$(\var{bnf},\var{bound},\{\var{arch}\})$: \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}. \subsecidx{bnrinit}$(\var{bnf},f,\{\fl=0\})$: \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. 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. 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. \subsecidx{bnrisconductor}$(A,\{B\},\{C\})$: \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}. \subsecidx{bnrisprincipal}$(\var{bnr},x,\{\fl=1\})$: \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 \subsecidx{bnrrootnumber}$(\var{bnr},\var{chi},\{\fl=0\})$: \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}. \subsecidx{bnrstark}$(\var{bnr},\{\var{subgroup}\})$: \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}. \subsecidx{dirzetak}$(\var{nf},b)$: \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}. \subsecidx{factornf}$(x,t)$: \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}. \subsecidx{galoisexport}$(\var{gal},\{\fl\})$: \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}. \subsecidx{galoisfixedfield}$(\var{gal},\var{perm},\{\fl\},\{v=y\})$: \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. \subsecidx{galoisgetpol}$(a,\{b\},\{s\})$: \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 \kbd{pol} is the polynomial and \kbd{den} is the common denominator of the conjugates expressed as a polynomial in a root of \kbd{pol}, which can be passed as an optional argument to \tet{galoisinit} and \tet{nfgaloisconj} as follows: \bprog V=galoisgetpol(8,4,1); G=galoisinit(V[1], V[2]) \\ passing V[2] speeds up the computation @eprog If $b$ and $s$ are omitted, return the number of isomorphic class 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. \subsecidx{galoisidentify}$(\var{gal})$: \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}. \subsecidx{galoisinit}$(\var{pol},\{\var{den}\})$: \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}. \subsecidx{idealramgroups}$(\var{nf},\var{gal},\var{pr})$: \label{se:idealramgroups}Let $K$ be the number field defined by $nf$ and assume $K/\Q$ be a Galois extension with Galois group $G$ given \kbd{gal=galoisinit(nf)}, and that $pr$ is 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 ramification group of $\goth{P}$. 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$. \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}. \subsecidx{idealred}$(\var{nf},I,\{v=0\})$: \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}. \subsecidx{idealstar}$(\var{nf},I,\{\fl=1\})$: \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. 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. \subsecidx{idealtwoelt}$(\var{nf},x,\{a\})$: \label{se:idealtwoelt}computes a two-element representation of the ideal $x$ in the number field $\var{nf}$, combining a random search and an explicit approximation theorem. $x$ is an ideal in any form (possibly an extended ideal, whose principal part is ignored) and the result is a row vector $[a,\alpha]$ with two components such that $x=a\Z_K+\alpha\Z_K$ and $a\in\Z$, where $a$ is the one passed as argument if any. Unless $x$ was given as a principal ideal, $a$ is chosen to be the positive generator of $x\cap\Z$. Note that when an explicit $a$ is given, we must factor it and this may be costly. When $a$ is omitted, we use a fast lazy factorization of $x\cap \Z$, yielding an algorithm in randomized polynomial time (and generally much faster in practice). 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}. \subsecidx{idealval}$(\var{nf},x,\var{pr})$: \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}. \subsecidx{matalgtobasis}$(\var{nf},x)$: \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}. \subsecidx{matbasistoalg}$(\var{nf},x)$: \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}. \subsecidx{modreverse}$(z)$: \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) *** at top-level: modreverse(u) *** ^------------- *** modreverse: reverse polmod does not exist: Mod(-x^3+9*x, x^4-10*x^2+1). ? minpoly(u) %6 = x^2 - 8 @eprog The library syntax is \fun{GEN}{modreverse}{GEN z}. \subsecidx{newtonpoly}$(x,p)$: \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}. \subsecidx{nfalgtobasis}$(\var{nf},x)$: \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}. \subsecidx{nfbasis}$(x,\{\fl=0\},\{\var{fa}\})$: \label{se:nfbasis}\idx{integral basis} of the number field defined by the irreducible, preferably monic, polynomial $x$, using a modified version of the \idx{round 4} algorithm by default, due to David \idx{Ford}, Sebastian \idx{Pauli} and Xavier \idx{Roblot}. The binary digits of $\fl$ have the following meaning: 1: assume that no square of a prime greater than the default \kbd{primelimit} divides the discriminant of $x$, i.e.~that the index of $x$ has only small prime divisors. 2: use \idx{round 2} algorithm. For small degrees and coefficient size, this is sometimes a little faster. (This program is the translation into C of a program written by David \idx{Ford} in Algeb.) Thus for instance, if $\fl=3$, this uses the round 2 algorithm and outputs an order which will be maximal at all the small primes. If \var{fa} is present, we assume (without checking!) that it is the two-column matrix of the factorization of the discriminant of the polynomial $x$. Note that it does \emph{not} have to be a complete factorization. This is especially useful if only a local integral basis for some small set of places is desired: only factors with exponents greater or equal to 2 will be considered. The library syntax is \fun{GEN}{nfbasis0}{GEN x, long flag, GEN fa = NULL}. An extended version is \fun{GEN}{nfbasis}{GEN x, GEN *d, long flag, GEN fa = NULL}, where \kbd{*d} receives the discriminant of the number field (\emph{not} of the polynomial $x$). \subsecidx{nfbasistoalg}$(\var{nf},x)$: \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}. \subsecidx{nfdetint}$(\var{nf},x)$: \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}. \subsecidx{nfdisc}$(x,\{\fl=0\},\{\var{fa}\})$: \label{se:nfdisc}\idx{field discriminant} of the number field defined by the integral, preferably monic, irreducible polynomial $x$. $\fl$ and $fa$ are exactly as in \kbd{nfbasis}. That is, $fa$ provides the matrix of a partial factorization of the discriminant of $x$, and binary digits of $\fl$ are as follows: 1: assume that no square of a prime greater than \kbd{primelimit} divides the discriminant. 2: use the round 2 algorithm, instead of the default \idx{round 4}. This should be slower except maybe for polynomials of small degree and coefficients. The library syntax is \fun{GEN}{nfdisc0}{GEN x, long flag, GEN fa = NULL}. Also available is \fun{GEN}{nfdisc}{GEN x} ($\fl=0$). \subsecidx{nfeltadd}$(\var{nf},x,y)$: \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}. \subsecidx{nfeltdiv}$(\var{nf},x,y)$: \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}. \subsecidx{nfeltdiveuc}$(\var{nf},x,y)$: \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}. \subsecidx{nfeltdivmodpr}$(\var{nf},x,y,\var{pr})$: \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. \subsecidx{nfeltdivrem}$(\var{nf},x,y)$: \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}. \subsecidx{nfeltmod}$(\var{nf},x,y)$: \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}. \subsecidx{nfeltmul}$(\var{nf},x,y)$: \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}. \subsecidx{nfeltmulmodpr}$(\var{nf},x,y,\var{pr})$: \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. \subsecidx{nfeltnorm}$(\var{nf},x)$: \label{se:nfeltnorm}returns the absolute norm of $x$. The library syntax is \fun{GEN}{nfnorm}{GEN nf, GEN x}. \subsecidx{nfeltpow}$(\var{nf},x,k)$: \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$. \subsecidx{nfeltpowmodpr}$(\var{nf},x,k,\var{pr})$: \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. \subsecidx{nfeltreduce}$(\var{nf},a,\var{id})$: \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}. \subsecidx{nfeltreducemodpr}$(\var{nf},x,\var{pr})$: \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. \subsecidx{nfelttrace}$(\var{nf},x)$: \label{se:nfelttrace}returns the absolute trace of $x$. The library syntax is \fun{GEN}{nftrace}{GEN nf, GEN x}. \subsecidx{nfeltval}$(\var{nf},x,\var{pr})$: \label{se:nfeltval}given an element $x$ in \var{nf} and a prime ideal \var{pr} in the format output by \kbd{idealprimedec}, computes their the valuation at \var{pr} of the element $x$. The same result could be obtained using \kbd{idealval(\var{nf},x,\var{pr})} (since $x$ would then be converted to a principal ideal), but it would be less efficient. The library syntax is \fun{long}{nfval}{GEN nf, GEN x, GEN pr}. \subsecidx{nffactor}$(\var{nf},x)$: \label{se:nffactor}factorization of the univariate polynomial $x$ over the number field $\var{nf}$ given by \kbd{nfinit}. $x$ has coefficients in $\var{nf}$ (i.e.~either scalar, polmod, polynomial or column vector). The main variable of $\var{nf}$ must be of \emph{lower} priority than that of $x$ (see \secref{se:priority}). However if the polynomial defining the number field occurs explicitly in the coefficients of $x$ (as modulus of a \typ{POLMOD}), its main variable must be \emph{the same} as the main variable of $x$. 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\noindent 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: factors 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}{nffactor}{GEN nf, GEN x}. \subsecidx{nffactorback}$(\var{nf},f,\{e\})$: \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}. \subsecidx{nffactormod}$(\var{nf},\var{pol},\var{pr})$: \label{se:nffactormod}factorization of the univariate polynomial $x$ modulo the prime ideal \var{pr} in the number field $\var{nf}$. $x$ can have coefficients in the number field (scalar, polmod, polynomial, column vector) or modulo the prime ideal (intmod modulo the rational prime under \var{pr}, polmod or polynomial with intmod coefficients, column vector of intmod). The prime ideal \var{pr} \emph{must} be in the format output by \kbd{idealprimedec}. 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}). The library syntax is \fun{GEN}{nffactormod}{GEN nf, GEN pol, GEN pr}. \subsecidx{nfgaloisapply}$(\var{nf},\var{aut},x)$: \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 specificed 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}. \subsecidx{nfgaloisconj}$(\var{nf},\{\fl=0\},\{d\})$: \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. \subsecidx{nfhilbert}$(\var{nf},a,b,\{\var{pr}\})$: \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). \subsecidx{nfhnf}$(\var{nf},x)$: \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. \subsecidx{nfhnfmod}$(\var{nf},x,\var{detx})$: \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}. \subsecidx{nfinit}$(\var{pol},\{\fl=0\})$: \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 In case \var{pol} has a huge discriminant which is difficult to factor, the special input format $[\var{pol},B]$ is also accepted where \var{pol} is a polynomial as above and $B$ is the integer basis, as would be computed by \tet{nfbasis}. This is useful if the integer basis is known in advance, or was computed conditionally. \bprog ? pol = polcompositum(x^5 - 101, polcyclo(7))[1]; ? B = nfbasis(pol, 1); \\ faster than nfbasis(pol), but conditional ? nf = nfinit( [pol, B] ); ? factor( abs(nf.disc) ) [5 18] [7 25] [101 24] @eprog \kbd{B} is conditional when its discriminant, which is \kbd{nf.disc}, can't be factored. In this example, the above factorization 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 \kbd{polred} 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$, does a \kbd{polred} 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 a \kbd{polred} reduction. 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}: slow down the routine by using an obsolete normalization algorithm (do not use this one!), \item \tet{nf_PARTIALFACT}: lazy factorization of the polynomial discriminant. Result is conditional unless the \emph{field} discriminant obtained is fully factored by \bprog Z_factor_limit(disc, 0) @eprog\noindent Namely the ``maximal order'' may not be maximal at any prime bigger than \kbd{primelimit} dividing the field discriminant. \subsecidx{nfisideal}$(\var{nf},x)$: \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}. \subsecidx{nfisincl}$(x,y)$: \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}. \subsecidx{nfisisom}$(x,y)$: \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}. \subsecidx{nfkermodpr}$(\var{nf},x,\var{pr})$: \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. \subsecidx{nfmodprinit}$(\var{nf},\var{pr})$: \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}. \subsecidx{nfnewprec}$(\var{nf})$: \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}. \subsecidx{nfroots}$(\{\var{nf}\},x)$: \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}$. \subsecidx{nfrootsof1}$(\var{nf})$: \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. \subsecidx{nfsnf}$(\var{nf},x)$: \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}. \subsecidx{nfsolvemodpr}$(\var{nf},a,b,\var{pr})$: \label{se:nfsolvemodpr}solution of $a\cdot x = b$ in $\Z_K/\var{pr}$, where $a$ is a matrix and $b$ a column vector, and where \var{pr} is in \key{modpr} format (see \kbd{nfmodprinit}). The library syntax is \fun{GEN}{nfsolvemodpr}{GEN nf, GEN a, GEN b, 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. \subsecidx{nfsubfields}$(\var{pol},\{d=0\})$: \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}. \subsecidx{polcompositum}$(P,Q,\{\fl=0\})$: \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. Assuming $P$ is irreducible (of smaller degree than $Q$ for efficiency), it is in general \emph{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 quite often defined by a complicated polynomial, which it is advisable to reduce before further work. Here is a simple example involving the field $\Q(\zeta_5, 5^{1/5})$: \bprog ? z = polcompositum(x^5 - 5, polcyclo(5), 1)[1]; ? pol = z[1] \\@com \kbd{pol} defines the compositum %2 = 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 = z[2]; a^5 - 5 \\@com \kbd{a} is a fifth root of $5$ %3 = 0 ? z = polredabs(pol, 1); \\@com look for a simpler polynomial ? pol = z[1] %5 = x^20 + 25*x^10 + 5 ? a = subst(a.pol, x, z[2]) \\@com \kbd{a} in the new coordinates %6 = Mod(-5/22*x^19 + 1/22*x^14 - 123/22*x^9 + 9/11*x^4, x^20 + 25*x^10 + 5) @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$). \subsecidx{polgalois}$(x)$: \label{se:polgalois}\idx{Galois} group of the non-constant polynomial $x\in\Q[X]$. In the present version \vers, $x$ must be irreducible and the degree of $x$ must be less than or equal to 7. On certain versions for which the data file of Galois resolvents has been installed (available in the Unix distribution as a separate package), degrees 8, 9, 10 and 11 are also implemented. 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_n$, $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 $n > 7$, $k$ is the numbering of the group among all transitive subgroups of $S_n$, 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 $n \leq 7$, it was ad hoc, so as to ensure that a given triple would design a unique group. Specifically, for polynomials of degree $\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 x, long prec}. To enable the new format in library mode, set the global variable \tet{new_galois_format} to $1$. \subsecidx{polred}$(x,\{\fl=0\},\{\var{fa}\})$: \label{se:polred}finds polynomials with reasonably small coefficients defining subfields of the number field defined by $x$. One of the polynomials always defines $\Q$ (hence is equal to $x-1$), and another always defines the same number field as $x$ if $x$ is irreducible. All $x$ accepted by \tet{nfinit} are also allowed here (e.g. non-monic polynomials, \kbd{nf}, \kbd{bnf}, \kbd{[x,Z\_K\_basis]}). 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. 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\noindent If $fa$ is given, it is assumed that it is the two-column matrix of the factorization of the discriminant of the polynomial $x$. The library syntax is \fun{GEN}{polred0}{GEN x, long flag, GEN fa = NULL}. Also available is \fun{GEN}{polred}{GEN x} ($\fl = 0$). The function \kbd{polred0} is provided for backward compatibility; instead of the above hardcoded numerical flags (which happen to be inconsistent), one should use \fun{GEN}{Polred}{GEN x, long flag, GEN fa} where flag is an or-ed combination of \tet{nf_PARTIALFACT} (partial factorization of the discriminant) and \tet{nf_ORIG} (give also elements). \subsecidx{polredabs}$(T,\{\fl=0\})$: \label{se:polredabs}returns a canonical defining polynomial $P$ for the same number field 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: non-monic polynomials, \kbd{nf}, \kbd{bnf}, \kbd{[T, Z\_K\_basis]}. \misctitle{Warning} This routine uses an exponential-time algorithm to enumerate all potential generators, and may be exceedingly slow when the number field has many subfields, hence a lot of elements of small $T_2$-norm. E.g. do not try it on the compositum of many quadratic fields; in that case, use \tet{polred} instead. 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. The primes dividing the index of the order chosen are larger than \tet{primelimit} or divide integers stored in the \tet{addprimes} table. In that case the polynomial $P$ is no longer canonical, and it may happen that it does not have minimal $T_2$ norm. You should always include this flag; without it, the routine will often spend infinite time trying to factor the discriminant of $T$. As long as the discriminant of the \emph{field} $\Q[X]/(T)$ is easy to factor (has at most one large prime factor not in the \kbd{addprimes} table), the result is the same. 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}: partial factorization of the discriminant, possibly work in a non-maximal order. You should always include this. \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. \subsecidx{polredord}$(x)$: \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{polred(,1)} or \kbd{polredabs(,16)}. The library syntax is \fun{GEN}{ordred}{GEN x}. \subsecidx{poltschirnhaus}$(x)$: \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}. \subsecidx{rnfalgtobasis}$(\var{rnf},x)$: \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}. \subsecidx{rnfbasis}$(\var{bnf},M)$: \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}. \subsecidx{rnfbasistoalg}$(\var{rnf},x)$: \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}. \subsecidx{rnfcharpoly}$(\var{nf},T,a,\{\var{var}=x\})$: \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. \subsecidx{rnfconductor}$(\var{bnf},\var{pol})$: \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, long }. \subsecidx{rnfdedekind}$(\var{nf},\var{pol},\{\var{pr}\},\{\fl=0\})$: \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}. \subsecidx{rnfdet}$(\var{nf},M)$: \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}. \subsecidx{rnfdisc}$(\var{nf},\var{pol})$: \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}. \subsecidx{rnfeltabstorel}$(\var{rnf},x)$: \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. The library syntax is \fun{GEN}{rnfelementabstorel}{GEN rnf, GEN x}. \subsecidx{rnfeltdown}$(\var{rnf},x)$: \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 an error will occur). If $x$ is given on the relative integral basis, apply \kbd{rnfbasistoalg} first, otherwise PARI will believe you are dealing with a vector. The library syntax is \fun{GEN}{rnfelementdown}{GEN rnf, GEN x}. \subsecidx{rnfeltreltoabs}$(\var{rnf},x)$: \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}. If $x$ is given on the relative integral basis, apply \kbd{rnfbasistoalg} first, otherwise PARI will believe you are dealing with a vector. The library syntax is \fun{GEN}{rnfelementreltoabs}{GEN rnf, GEN x}. \subsecidx{rnfeltup}$(\var{rnf},x)$: \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$ expressed as a polynomial or polmod, computes $x$ as an element of the absolute extension $L/\Q$ as a polynomial modulo the absolute equation \kbd{\var{rnf}.pol}. If $x$ is given on the integral basis of $K$, apply \kbd{nfbasistoalg} first, otherwise PARI will believe you are dealing with a vector. The library syntax is \fun{GEN}{rnfelementup}{GEN rnf, GEN x}. \subsecidx{rnfequation}$(\var{nf},\var{pol},\{\fl=0\})$: \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 the absolute equation of $L$ over $\Q$. If $\fl$ is non-zero, outputs a 3-component row vector $[z,a,k]$, where $z$ is the absolute equation of $L$ over $\Q$, as in the default behavior, $a$ expresses as an element of $L$ a root $\alpha$ of the polynomial defining the base field $\var{nf}$, and $k$ is a small integer such that $\theta = \beta+k\alpha$ where $\theta$ is a root of $z$ and $\beta$ a root of $\var{pol}$. 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, an error message will be issued. 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$). \subsecidx{rnfhnfbasis}$(\var{bnf},x)$: \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}. \subsecidx{rnfidealabstorel}$(\var{rnf},x)$: \label{se:rnfidealabstorel}let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit}, and $x$ 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$. If $x$ is an ideal in HNF form, associated to an \var{nf} structure, for instance as output by $\tet{idealhnf}(\var{nf},\dots)$, use \kbd{rnfidealabstorel(rnf, nf.zk * x)} to convert it to a relative ideal. The library syntax is \fun{GEN}{rnfidealabstorel}{GEN rnf, GEN x}. \subsecidx{rnfidealdown}$(\var{rnf},x)$: \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}), 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}. \subsecidx{rnfidealhnf}$(\var{rnf},x)$: \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}{rnfidealhermite}{GEN rnf, GEN x}. \subsecidx{rnfidealmul}$(\var{rnf},x,y)$: \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}. \subsecidx{rnfidealnormabs}$(\var{rnf},x)$: \label{se:rnfidealnormabs}$\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 norm of the ideal $x$ considered as an ideal of the absolute extension $L/\Q$. This is identical to \kbd{idealnorm(rnfidealnormrel(\var{rnf},x))}, but faster. The library syntax is \fun{GEN}{rnfidealnormabs}{GEN rnf, GEN x}. \subsecidx{rnfidealnormrel}$(\var{rnf},x)$: \label{se:rnfidealnormrel}$\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 relative norm of $x$ as a ideal of $K$ in HNF. The library syntax is \fun{GEN}{rnfidealnormrel}{GEN rnf, GEN x}. \subsecidx{rnfidealreltoabs}$(\var{rnf},x)$: \label{se:rnfidealreltoabs}$\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being a relative ideal, gives 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 following routine might be useful: \bprog \\ return y = rnfidealreltoabs(rnf,...) as an ideal in HNF form \\ associated to nf = nfinit( rnf.pol ); idealgentoHNF(nf, y) = mathnf( Mat( nfalgtobasis(nf, y) ) ); @eprog The library syntax is \fun{GEN}{rnfidealreltoabs}{GEN rnf, GEN x}. \subsecidx{rnfidealtwoelt}$(\var{rnf},x)$: \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}. \subsecidx{rnfidealup}$(\var{rnf},x)$: \label{se:rnfidealup}$\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an ideal of $K$, gives 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 following routine might be useful: \bprog \\ return y = rnfidealup(rnf,...) as an ideal in HNF form \\ associated to nf = nfinit( rnf.pol ); idealgentoHNF(nf, y) = mathnf( Mat( matalgtobasis(nf, y) ) ); @eprog The library syntax is \fun{GEN}{rnfidealup}{GEN rnf, GEN x}. \subsecidx{rnfinit}$(\var{nf},\var{pol})$: \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 all the necessary 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}$, $m$ the degree of the base field, $n$ the relative degree, $L$ the large field (of relative degree $n$ or absolute degree $nm$), $r_1$ and $r_2$ the number of real and complex places of $K$. $\var{rnf}[1]$ contains the relative polynomial \var{pol}. $\var{rnf}[2]$ is currently unused. $\var{rnf}[3]$ 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]$ 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]$ is a two-component row vector, where the first component is the relative integral pseudo basis expressed as polynomials (in the variable of $pol$) with polmod coefficients in $\var{nf}$, and the second component 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]$ is $\var{nf}$. $\var{rnf}[11]$ is the output of \kbd{rnfequation(nf, pol, 1)}. Namely, a vector \var{vabs} with 3 entries describing the \emph{absolute} extension $L/\Q$. $\var{vabs}[1]$ is an absolute equation, more conveniently obtained as \kbd{rnf.pol}. $\var{vabs}[2]$ expresses the generator $\alpha$ of the number field $\var{nf}$ as a polynomial modulo the absolute equation $\var{vabs}[1]$. $\var{vabs}[3]$ is a small integer $k$ such that, if $\beta$ is an abstract root of \var{pol} and $\alpha$ the generator of $\var{nf}$, the generator whose root is \var{vabs} will be $\beta + k \alpha$. Note that one must be very careful if $k\neq0$ when dealing simultaneously with absolute and relative quantities since 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 strongly advise to change the relative polynomial so that its root will be $\beta + k \alpha$. Typically, the GP instruction would be \kbd{pol = subst(pol, x, x - k*Mod(y,\var{nf}.pol))} $\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}. \subsecidx{rnfisabelian}$(\var{nf},T)$: \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}. \subsecidx{rnfisfree}$(\var{bnf},x)$: \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}. \subsecidx{rnfisnorm}$(T,a,\{\fl=0\})$: \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}. \subsecidx{rnfisnorminit}$(\var{pol},\var{polrel},\{\fl=2\})$: \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}. \subsecidx{rnfkummer}$(\var{bnr},\{\var{subgp}\},\{d=0\})$: \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}. \subsecidx{rnflllgram}$(\var{nf},\var{pol},\var{order})$: \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}. \subsecidx{rnfnormgroup}$(\var{bnr},\var{pol})$: \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}. \subsecidx{rnfpolred}$(\var{nf},\var{pol})$: \label{se:rnfpolred}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{rnfpolredabs}. The library syntax is \fun{GEN}{rnfpolred}{GEN nf, GEN pol, long prec}. \subsecidx{rnfpolredabs}$(\var{nf},\var{pol},\{\fl=0\})$: \label{se:rnfpolredabs}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 1: returns $[P,a]$ where $P$ is the default output and $a$ is an element expressed on a root of $P$ whose characteristic polynomial is \var{pol} 2: returns an absolute polynomial (same as {\tt rnfequation(\var{nf},rnfpolredabs(\var{nf},\var{pol}))} but faster). 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{Remark} In the present implementation, this is both faster and much more efficient than \kbd{rnfpolred}, the difference being more dramatic than in the absolute case. This is because the implementation of \kbd{rnfpolred} is based on (a partial implementation of) an incomplete reduction theory of lattices over number fields, the function \kbd{rnflllgram}, which deserves to be improved. The library syntax is \fun{GEN}{rnfpolredabs}{GEN nf, GEN pol, long flag}. \subsecidx{rnfpseudobasis}$(\var{nf},\var{pol})$: \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}. \subsecidx{rnfsteinitz}$(\var{nf},x)$: \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}. \subsecidx{subgrouplist}$(\var{bnr},\{\var{bound}\},\{\fl=0\})$: \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}. \subsecidx{zetak}$(\var{nfz},x,\{\fl=0\})$: \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}. \subsecidx{zetakinit}$(\var{bnf})$: \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. 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. \subsecidx{O}$(p\hbox{\kbd{\pow}}e)$: \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$. \subsecidx{deriv}$(x,\{v\})$: \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. \subsecidx{diffop}$(x,v,d,\{n=1\})$: \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. \subsecidx{eval}$(x)$: \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. For convenience, $x$ is evaluated as if \kbd{strictmatch} was off. In particular, unused characters at the end of $x$ do not prevent its evaluation: \bprog ? eval("1a") *** eval: Warning: unused characters: a. % 1 = 1 @eprog \synt{geval}{GEN x}. \subsecidx{factorpadic}$(\var{pol},p,r,\{\fl=0\})$: \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}. The factors are normalized so that their leading coefficient is a power of $p$. $r$ must be strictly larger than the $p$-adic valuation of the discriminant of \var{pol} for the result to make any sense. The method used is a modified version of the \idx{round 4} algorithm of \idx{Zassenhaus}. If $\fl=1$, use an algorithm due to \idx{Buchmann} and \idx{Lenstra}, which is much less efficient. The library syntax is \fun{GEN}{factorpadic0}{GEN pol, GEN p, long r, long flag}. \fun{GEN}{factorpadic}{GEN f,GEN p, long r} corresponds to the default $\fl=0$. \subsecidx{intformal}$(x,\{v\})$: \label{se:intformal}\idx{formal integration} of $x$ with respect to the main variable if $v$ is omitted, with respect to the variable $v$ otherwise. Since PARI does not know about ``abstract'' logarithms (they are immediately evaluated, if only to a power series), logarithmic terms in the result will yield an error. $x$ can be of any type. When $x$ is a rational function, it is assumed that the base ring is an integral domain of characteristic zero. The library syntax is \fun{GEN}{integ}{GEN x, long v = -1}, where \kbd{v} is a variable number. \subsecidx{padicappr}$(\var{pol},a)$: \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}. \subsecidx{padicfields}$(p, N, \{\fl=0\})$: \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 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$. \subsecidx{polchebyshev}$(n,\{\fl=1\},\{a='x\})$: \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}{polchebyshev1}{long n, long v} and \fun{GEN}{polchebyshev2}{long n, long v} for $T_n$ and $U_n$ respectively. \subsecidx{polcoeff}$(x,n,\{v\})$: \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, vector or matrix types are also accepted for $x$, and the meaning is then identical with that of \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. \subsecidx{polcyclo}$(n,\{a = 'x\})$: \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 can deal with all rational values $a$; otherwise it assumes that $a^d - 1$ is invertible for all $d\mid n$. If this is not the case, 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$. \subsecidx{poldegree}$(x,\{v\})$: \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. \subsecidx{poldisc}$(\var{pol},\{v\})$: \label{se:poldisc}discriminant of the polynomial \var{pol} in the main variable if $v$ is omitted, in $v$ otherwise. The algorithm used is the \idx{subresultant algorithm}. The library syntax is \fun{GEN}{poldisc0}{GEN pol, long v = -1}, where \kbd{v} is a variable number. \subsecidx{poldiscreduced}$(f)$: \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}. \subsecidx{polhensellift}$(A, B, p, e)$: \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)] ? lift(lift( 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}. \subsecidx{polhermite}$(n,\{a='x\})$: \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$. \subsecidx{polinterpolate}$(X,\{Y\},\{x\},\{\&e\})$: \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}. \subsecidx{polisirreducible}$(\var{pol})$: \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{GEN}{gisirreducible}{GEN pol}. \subsecidx{pollead}$(x,\{v\})$: \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. \subsecidx{pollegendre}$(n,\{a='x\})$: \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}. \subsecidx{polrecip}$(\var{pol})$: \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}. \subsecidx{polresultant}$(x,y,\{v\},\{\fl=0\})$: \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 = res(x,y)$, use the \tet{bezoutres} 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. \subsecidx{polroots}$(x,\{\fl=0\})$: \label{se:polroots}complex roots of the polynomial \var{pol}, 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 implemented by X.~Gourdon. Barring bugs, it is guaranteed to converge and to give the roots to the required accuracy. If $\fl=1$, use a variant of the Newton-Raphson method, which is \emph{not} guaranteed to converge, nor to give accurate results, but is rather fast when it does. If you get the messages ``too many iterations in roots'' or ``INTERNAL ERROR: incorrect result in roots'', use the default algorithm. The library syntax is \fun{GEN}{roots0}{GEN x, long flag, long prec}. Also available is \fun{GEN}{roots}{GEN x, long prec}, as well as \fun{GEN}{cleanroots}{GEN x, long prec} which ensures that real roots of real polynomials are returned as \typ{REAL} (instead of \typ{COMPLEX}s with 0 imaginary part). \subsecidx{polrootsmod}$(\var{pol},p,\{\fl=0\})$: \label{se:polrootsmod}row vector of roots modulo $p$ of the polynomial \var{pol}. The particular non-prime value $p=4$ is accepted, mainly for $2$-adic computations. Multiple roots are \emph{not} repeated. \bprog ? polrootsmod(x^2-1,2) %1 = [Mod(1, 2)]~ ? polrootsmod(x^2-1,4) %2 = [Mod(1, 4), Mod(3, 4)]~ @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}. \subsecidx{polrootspadic}$(x,p,r)$: \label{se:polrootspadic}row vector of $p$-adic roots of the polynomial \var{pol}, given to $p$-adic precision $r$. Multiple roots are \emph{not} repeated. $p$ is assumed to be a prime, and \var{pol} to be non-zero modulo $p$. 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$. If \var{pol} has inexact \typ{PADIC} coefficients, this is not always well-defined; in this case, the equation is first made integral, then lifted to $\Z$. Hence the roots given are approximations of the roots of a polynomial which is $p$-adically close to the input. The library syntax is \fun{GEN}{rootpadic}{GEN x, GEN p, long r}. \subsecidx{polsturm}$(\var{pol},\{a\},\{b\})$: \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). \subsecidx{polsubcyclo}$(n,d,\{v=x\})$: \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 more closely 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. \subsecidx{polsylvestermatrix}$(x,y)$: \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}. \subsecidx{polsym}$(x,n)$: \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}. \subsecidx{poltchebi}$(n,\{v=x\})$: \label{se:poltchebi}creates the $n^{\text{th}}$ \idx{Chebyshev} polynomial~$T_n$ of the first kind in variable $v$. This function is retained for backward compatibility only. Use \tet{polchebyshev}. The library syntax is \fun{GEN}{polchebyshev1}{long n, long v = -1}, where \kbd{v} is a variable number. \subsecidx{polzagier}$(n,m)$: \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}. \subsecidx{serconvol}$(x,y)$: \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}. \subsecidx{serlaplace}$(x)$: \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}. \subsecidx{serreverse}$(x)$: \label{se:serreverse}reverse power series (i.e.~$x^{-1}$, not $1/x$) of $x$. $x$ must be a power series whose valuation is exactly equal to one. The library syntax is \fun{GEN}{recip}{GEN x}. \subsecidx{subst}$(x,y,z)$: \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. \subsecidx{substpol}$(x,y,z)$: \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). \subsecidx{substvec}$(x,v,w)$: \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}. \subsecidx{taylor}$(x,t,\{d=\var{seriesprecision}\})$: \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. \subsecidx{thue}$(\var{tnf},a,\{\var{sol}\})$: \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. 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 favourable 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 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.ref %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}. \subsecidx{thueinit}$(P,\{\fl=0\})$: \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$. \subsecidx{algdep}$(x,k,\{\fl=0\})$: \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. If \tet{lindep} is not able to find a relation and returns a lower bound for the sup norm of the smallest relation, \tet{algdep} returns that bound instead. 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 \\\\\\\\\ LLL ? \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 \\\\\\\\\ PSLQ ? \p200 ? algdep(2^(1/6)+3^(1/5), 30, -3); \\ failure in 15s ? \p250 ? algdep(2^(1/6)+3^(1/5), 30, -3); \\ right in 20s ? \p500 ? algdep(2^(1/6)+3^(1/5), 30, -3); \\ right in 52s ? \p1000 ? algdep(2^(1/6)+3^(1/5), 30, -3); \\ right in 164s @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. Interestingly enough, our PSLQ also reliably succeeds from 205 digits on (and is 15 times slower at that accuracy). 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 paper concludes in the superiority of the PSLQ algorithm, which either shows that PARI's implementation of PSLQ is lacking, or that its LLL is extremely good. 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$). \subsecidx{charpoly}$(A,\{v=x\},\{\fl=3\})$: \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. If $A$ is not a square matrix, it returns the characteristic polynomial of the map ``multiplication by $A$'' if $A$ is a scalar, in particular a polmod. E.g.~\kbd{charpoly(I) = x\pow2+1}. The value of $\fl$ is only significant for matrices. 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. In practice one should use the default (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}{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. \subsecidx{concat}$(x,\{y\})$: \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, it is easy to concatenate them vertically. To concatenate vectors sideways (i.e.~to obtain a two-row or two-column matrix), use \tet{Mat} instead (see the example there). 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 definitely \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)}. \subsecidx{lindep}$(x,\{\fl=0\})$: \label{se:lindep}\sidx{linear dependence}$x$ being a vector with $p$-adic or real/complex coefficients, finds a small integral linear combination among these coefficients. If $x$ is $p$-adic, $\fl$ is meaningless and the algorithm LLL-reduces a suitable (dual) lattice. Otherwise, the value of $\fl$ determines the algorithm used; in the current version of PARI, we suggest to use \emph{non-negative} values, since it is by far the fastest and most robust implementation. See the detailed example in \secref{se:algdep} (\kbd{algdep}). If $\fl\geq 0$, uses a floating point (variable precision) LLL algorithm. This is in general much faster than the other variants. 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. If $\fl=-1$, uses a variant of the \idx{LLL} algorithm due to Hastad, Lagarias and Schnorr (STACS 1986). If the precision is too low, the routine may enter an infinite loop. Faster than the alternatives if it converges, especially when the accuracy is much larger than what is really necessary; usually diverges, though. If $\fl=-2$, $x$ is allowed to be (and in any case interpreted as) a matrix. Returns a non trivial element of the kernel of $x$, or $0$ if $x$ has trivial kernel. The element is defined over the field of coefficients of $x$, and is in general not integral. If $\fl=-3$, uses the PSLQ algorithm. This may return a real number $B$, indicating that the input accuracy was exhausted and that no relation exist whose sup norm is less than $B$. If $\fl=-4$, uses an experimental 2-level PSLQ, which does not work at all. Don't use it! The library syntax is \fun{GEN}{lindep0}{GEN x, long flag}. Also available are \fun{GEN}{lindep}{GEN x} ($\fl=0$) \fun{GEN}{lindep2}{GEN x, long bit} ($\fl\geq 0$, bypasses the check for $p$-adic inputs) and \fun{GEN}{deplin}{GEN x} ($\fl=-2$). \subsecidx{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} \subsecidx{listinsert}$(L,x,n)$: \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}. \subsecidx{listkill}$(L)$: \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}. \subsecidx{listpop}$(\var{list},\{n\})$: \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. This runs in time $O(\#L - n + 1)$. The library syntax is \fun{void}{listpop}{GEN list, long n}. \subsecidx{listput}$(\var{list},x,\{n\})$: \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}. \subsecidx{listsort}$(L,\{\fl=0\})$: \label{se:listsort}sorts the \typ{LIST} \var{list} in place. If $\fl$ is non-zero, suppresses all repeated coefficients. This is faster than the \kbd{vecsort} command since no copy has to be made. No value returned. The library syntax is \fun{void}{listsort}{GEN L, long flag}. \subsecidx{matadjoint}$(x,\{\fl=0\})$: \label{se:matadjoint} \idx{adjoint matrix} of $x$, i.e.~the matrix $y$ of cofactors of $x$, satisfying $x*y=\det(x)*\Id$. $x$ must be a (non-necessarily invertible) square matrix of dimension $n$. If $\fl$ is 0 or omitted, use a fast algorithm which assumes that $n!$ is invertible. If $\fl$ is 1, use a slower division-free algorithm. \bprog ? a = [1,2,3;3,4,5;6,7,8] * Mod(1,2); ? matadjoint(a) *** at top-level: matadjoint([1,2,3;3, *** ^-------------------- *** matadjoint: impossible inverse modulo: Mod(0, 2). ? matadjoint(a, 1) \\ use safe algorithm %2 = [Mod(1, 2) Mod(1, 2) Mod(0, 2)] [Mod(0, 2) Mod(0, 2) Mod(0, 2)] [Mod(1, 2) Mod(1, 2) Mod(0, 2)] @eprog\noindent Both algorithms use $O(n^4)$ operations in the base ring. The library syntax is \fun{GEN}{matadjoint0}{GEN x, long flag}. Also available are \fun{GEN}{adj}{GEN x} (\fl=0) and \fun{GEN}{adjsafe}{GEN x} (\fl=1). \subsecidx{matcompanion}$(x)$: \label{se:matcompanion} the left companion matrix to the polynomial $x$. The library syntax is \fun{GEN}{matcompanion}{GEN x}. \subsecidx{matdet}$(x,\{\fl=0\})$: \label{se:matdet}determinant of $x$. $x$ must be a square matrix. If $\fl=0$, uses Gauss-Bareiss. If $\fl=1$, uses classical Gaussian elimination, which is better when the entries of the matrix are reals or integers for example, but usually much worse for more complicated entries like multivariate polynomials. The library syntax is \fun{GEN}{det0}{GEN x, long flag}. Also available are \fun{GEN}{det}{GEN x} ($\fl=0$) and \fun{GEN}{det2}{GEN x} ($\fl=1$). \subsecidx{matdetint}$(x)$: \label{se:matdetint} $x$ being an $m\times n$ matrix with integer coefficients, this function computes a non-zero \emph{multiple} of the determinant of the lattice generated by the columns of $x$ if it has maximal rank $m$, and returns zero otherwise, using the Gauss-Bareiss algorithm. When $x$ is square, the exact determinant is obtained. 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 the exact determinant using \bprog matdet( mathnfmod(x, matdetint(x)) ) @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(x, 1)} or \kbd{mathnf(x, 4)} directly. The library syntax is \fun{GEN}{detint}{GEN x}. \subsecidx{matdiagonal}$(x)$: \label{se:matdiagonal}$x$ being a vector, creates the diagonal matrix whose diagonal entries are those of $x$. The library syntax is \fun{GEN}{diagonal}{GEN x}. \subsecidx{mateigen}$(x)$: \label{se:mateigen}gives the eigenvectors of $x$ as columns of a matrix. The library syntax is \fun{GEN}{eigen}{GEN x, long prec}. \subsecidx{matfrobenius}$(M,\{\fl\},\{v=x\})$: \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. \subsecidx{mathess}$(x)$: \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}. \subsecidx{mathilbert}$(n)$: \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}. \subsecidx{mathnf}$(x,\{\fl=0\})$: \label{se:mathnf}if $x$ is a (not necessarily square) matrix with integer entries, 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$. If $\fl=0$, uses the naive algorithm. This is in general fastest but may require too much memory as the dimension gets large (bigger than 100, say), in which case you may try \kbd{mathnfmod(x, matdetint(x))} when $x$ has maximal rank, and \kbd{mathnf(x, 4)} otherwise. If $\fl=1$, outputs a two-component row vector $[H,U]$, where $H$ is the Hermite normal form of $x$ defined as above, and $U$ is the unimodular transformation matrix such that $xU=[0|H]$. When the kernel is large, $U$ has in general huge coefficients. In the worst case, the running time is exponential with respect to the dimension, but the routine behaves well in small dimension (less than 50 or 100, say). If $\fl=3$, 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 $xU$ gives $H$. This is in general slower than $\fl=1$ but the matrix $U$ is smaller; it may still be large. If $\fl=4$, as in case 1 above, but uses a variant of \idx{LLL} reduction along the way. The matrix $U$ is in general close to optimal (in terms of smallest $L_2$ norm), but the reduction is in general slow, although provably polynomial-time. The library syntax is \fun{GEN}{mathnf0}{GEN x, long flag}. Also available are \fun{GEN}{hnf}{GEN x} ($\fl=0$) and \fun{GEN}{hnfall}{GEN x} ($\fl=1$). To reduce \emph{huge} (say $400 \times 400$ and more) relation matrices (sparse with small entries), 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/alglin1.c}. \subsecidx{mathnfmod}$(x,d)$: \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}. \subsecidx{mathnfmodid}$(x,d)$: \label{se:mathnfmodid}outputs the (upper triangular) \idx{Hermite normal form} of $x$ concatenated with $d$ times the identity matrix. Assumes that $x$ has integer entries. The library syntax is \fun{GEN}{hnfmodid}{GEN x, GEN d}. \subsecidx{matid}$(n)$: \label{se:matid}creates the $n\times n$ identity matrix. The library syntax is \fun{GEN}{matid}{long n}. \subsecidx{matimage}$(x,\{\fl=0\})$: \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$). \subsecidx{matimagecompl}$(x)$: \label{se:matimagecompl}gives the vector of the column indices which are not extracted by the function \kbd{matimage}. 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}. \subsecidx{matindexrank}$(x)$: \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}. \subsecidx{matintersect}$(x,y)$: \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}. \subsecidx{matinverseimage}$(x,y)$: \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}. \subsecidx{matisdiagonal}$(x)$: \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}. \subsecidx{matker}$(x,\{\fl=0\})$: \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$). \subsecidx{matkerint}$(x,\{\fl=0\})$: \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). \subsecidx{matmuldiagonal}$(x,d)$: \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}. \subsecidx{matmultodiagonal}$(x,y)$: \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}. \subsecidx{matpascal}$(n,\{q\})$: \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}. \subsecidx{matrank}$(x)$: \label{se:matrank}rank of the matrix $x$. The library syntax is \fun{long}{rank}{GEN x}. \subsecidx{matrix}$(m,n,\{X\},\{Y\},\{\var{expr}=0\})$: \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} \subsecidx{matrixqz}$(A,\{p=0\})$: \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( vecextract(x, Str("^",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}. \subsecidx{matsize}$(x)$: \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}. \subsecidx{matsnf}$(X,\{\fl=0\})$: \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}. \subsecidx{matsolve}$(M,B)$: \label{se:matsolve}$M$ being an invertible matrix and $B$ a column vector, finds the solution $X$ of $MX=B$, using Gaussian elimination. This has the same effect as, but is a bit faster, than $M^{-1}*B$. The library syntax is \fun{GEN}{gauss}{GEN M, GEN B}. \subsecidx{matsolvemod}$(M,D,B,\{\fl=0\})$: \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$). \subsecidx{matsupplement}$(x)$: \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. The library syntax is \fun{GEN}{suppl}{GEN x}. \subsecidx{mattranspose}$(x)$: \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}. \subsecidx{minpoly}$(A,\{v=x\})$: \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. \subsecidx{qfgaussred}$(q)$: \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). \subsecidx{qfjacobi}$(x)$: \label{se:qfjacobi}$x$ being a real symmetric matrix, this gives a vector having two components: the first one is the vector of (real) eigenvalues of $x$, sorted in increasing order, the second is the corresponding orthogonal matrix of eigenvectors of $x$. The method used is Jacobi's method for symmetric matrices. The library syntax is \fun{GEN}{jacobi}{GEN x, long prec}. \subsecidx{qflll}$(x,\{\fl=0\})$: \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$). \subsecidx{qflllgram}$(G,\{\fl=0\})$: \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$). \subsecidx{qfminim}$(x,\{b\},\{m\},\{\fl=0\})$: \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 the first vector whose norm is less than $b$. In this variant, an explicit $b$ must be provided. 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$). \subsecidx{qfperfection}$(G)$: \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}. \subsecidx{qfrep}$(q,B,\{\fl=0\})$: \label{se:qfrep} $q$ being a square and symmetric matrix with integer entries representing a positive definite quadratic form, outputs the vector whose $i$-th entry, $1 \leq i \leq B$ is half the number of vectors $v$ such that $q(v) = i$. This routine uses a naive algorithm based on \tet{qfminim}, and will fail if any entry becomes larger than $2^{31}$. \noindent The binary digits of \fl\ mean: \item 1: count vectors of even norm from $1$ to $2B$. \item 2: return a \typ{VECSMALL} instead of a \typ{VEC} The library syntax is \fun{GEN}{qfrep0}{GEN q, GEN B, long flag}. \subsecidx{qfsign}$(x)$: \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}. \subsecidx{setintersect}$(x,y)$: \label{se:setintersect}intersection of the two sets $x$ and $y$ (see \kbd{setisset}). The function also works if both $x$ and $y$ are vectors of strictly increasing entries, according to \kbd{<}); in that case we return a vector of strictly increasing entries, not a set. Otherwise, the result is undefined. The library syntax is \fun{GEN}{setintersect}{GEN x, GEN y}. \subsecidx{setisset}$(x)$: \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 \typ{STR}s. 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}. \subsecidx{setminus}$(x,y)$: \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$. The function also works if both $x$ and $y$ are vectors of strictly increasing entries, according to \kbd{<}); in that case we return a vector of strictly increasing entries, not a set. Otherwise, the result is undefined. The library syntax is \fun{GEN}{setminus}{GEN x, GEN y}. \subsecidx{setsearch}$(S,x,\{\fl=0\})$: \label{se:setsearch}searches if $x$ belongs to the set $S$ (see \kbd{setisset}). A set is a vector of \typ{STR}, but this function works also if $S$ is a arbitrary \emph{sorted} vector or list (see \kbd{listsort}): if $x$ is not a \typ{STR}, we first replace it by \kbd{Str}$(x)$ \emph{unless} the first element of $S$ is also not a \typ{STR}. If $x$ belongs to the set and $\fl$ is zero or omitted, returns the index $j$ such that $S[j]=x$, otherwise returns 0. If $\fl$ is non-zero returns the index $j$ where $x$ should be inserted, and $0$ if it already belongs to $S$ (this is meant to be used in conjunction with \kbd{listinsert}, see below). \bprog ? T = [2,3,5,7]; S = Set(T); ? setsearch(S, 2) \\ search in a true set, t_INT 2 converted to string %2 = 1 ? setsearch(S, Str(2)) \\ search in a true set, no need for conversion %3 = 1 ? setsearch(T, 2) \\ search in a sorted vector, no need for conversion %4 = 1 ? setsearch(T, Str(2)) \\ search in a sorted vector, t_STR "2" not found %5 = 0 ? setsearch(S, 4) \\ not found %6 = 0 ? setsearch(S, 4, 1) \\ should have been inserted at index 3 %7 = 3 @eprog The library syntax is \fun{long}{setsearch}{GEN S, GEN x, long flag}. \subsecidx{setunion}$(x,y)$: \label{se:setunion}union of the two sets $x$ and $y$ (see \kbd{setisset}). The function also works if both $x$ and $y$ are vectors of strictly increasing entries, according to \kbd{<}); in that case we return a vector of strictly increasing entries, not a set. Otherwise, the result is undefined. The library syntax is \fun{GEN}{setunion}{GEN x, GEN y}. \subsecidx{trace}$(x)$: \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}. \subsecidx{vecextract}$(x,y,\{z\})$: \label{se:vecextract}extraction of components of the vector or matrix $x$ according to $y$. In case $x$ is a matrix, its components are as usual 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, 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{line} 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 library syntax is \fun{GEN}{extract0}{GEN x, GEN y, GEN z = NULL}. \subsecidx{vecsort}$(x,\{\var{cmp}\},\{\fl=0\})$: \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{cmp} is omitted, we use the standard comparison function \kbd{<}, thereby restricting the possible types for the elements of $x$ (integers, fractions or reals). If \kbd{cmp} 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{cmp}=\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],lex) \\ sort columns according to lex order %1 = [2 3] [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 ? cmp(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], cmp) @eprog\noindent The last example used the named \kbd{cmp} 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 2: sorts $x$ by ascending lexicographic order (as per the \kbd{lex} comparison function). \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 cmp = NULL, long flag}. \subsecidx{vector}$(n,\{X\},\{\var{expr}=0\})$: \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. Avoid modifying $X$ within \var{expr}; if you do, the formal variable still runs from $1$ to $n$. In particular, \kbd{vector(n,i,expr)} is not equivalent to \bprog v = vector(n) for (i = 1, n, v[i] = expr) @eprog\noindent 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} \subsecidx{vectorsmall}$(n,\{X\},\{\var{expr}=0\})$: \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} \subsecidx{vectorv}$(n,\{X\},\{\var{expr}=0\})$: \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}. \subsecidx{derivnum}$(X=a,\var{expr})$: \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$. \subsecidx{intcirc}$(X=a,R,\var{expr},\{\var{tab}\})$: \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}. \subsecidx{intfouriercos}$(X=a,b,z,\var{expr},\{\var{tab}\})$: \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}. \subsecidx{intfourierexp}$(X=a,b,z,\var{expr},\{\var{tab}\})$: \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}. \subsecidx{intfouriersin}$(X=a,b,z,\var{expr},\{\var{tab}\})$: \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}. \subsecidx{intfuncinit}$(X=a,b,\var{expr},\{\fl=0\},\{m=0\})$: \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. \subsecidx{intlaplaceinv}$(X=\var{sig},z,\var{expr},\{\var{tab}\})$: \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}. \subsecidx{intmellininv}$(X=\var{sig},z,\var{expr},\{\var{tab}\})$: \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}. \subsecidx{intmellininvshort}$(\var{sig},z,\var{tab})$: \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}. \subsecidx{intnum}$(X=a,b,\var{expr},\{\var{tab}\})$: \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}. \subsecidx{intnuminit}$(a,b,\{m=0\})$: \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}. \subsecidx{intnuminitgen}$(t,a,b,\var{ph},\{m=0\},\{\fl=0\})$: \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} \subsecidx{intnumromb}$(X=a,b,\var{expr},\{\fl=0\})$: \label{se:intnumromb}numerical integration of \var{expr} (smooth in $]a,b[$), with respect to $X$. This function is deprecated, use \tet{intnum} instead. 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 1e1000. However beware of real underflow when dealing with rapidly decreasing functions. For example, if one wants to compute the $\int_0^\infty e^{-x^2}\,dx$ to 28 decimal digits, then one should set infinity equal to 10 for example, and certainly not to 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}. \subsecidx{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}. \subsecidx{prod}$(X=a,b,\var{expr},\{x=1\})$: \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}. \subsecidx{prodeuler}$(X=a,b,\var{expr})$: \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}. \subsecidx{prodinf}$(X=a,\var{expr},\{\fl=0\})$: \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$). \subsecidx{solve}$(X=a,b,\var{expr})$: \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}. \subsecidx{sum}$(X=a,b,\var{expr},\{x=0\})$: \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}. \subsecidx{sumalt}$(X=a,\var{expr},\{\fl=0\})$: \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$). \subsecidx{sumdiv}$(n,X,\var{expr})$: \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). Arithmetic functions like \tet{sigma} use the multiplicativity of the underlying expression to speed up the computation. Since there is no way to indicate that \var{expr} is multiplicative in $n$, specialized functions should always be preferred. %\syn{NO} \subsecidx{suminf}$(X=a,\var{expr})$: \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}. \subsecidx{sumnum}$(X=a,\var{sig},\var{expr},\{\var{tab}\},\{\fl=0\})$: \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}. \subsecidx{sumnumalt}$(X=a,\var{sig},\var{expr},\{\var{tab}\},\{\fl=0\})$: \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}. \subsecidx{sumnuminit}$(\var{sig}, \{m=0\}, \{\var{sgn}=1\})$: \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}. \subsecidx{sumpos}$(X=a,\var{expr},\{\fl=0\})$: \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{And 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. \subsecidx{plot}$(X=a,b,\var{expr},\{\var{Ymin}\},\{\var{Ymax}\})$: \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 minima (resp. the maxima) of the computed values of the expression is used instead. \subsecidx{plotbox}$(w,\var{x2},\var{y2})$: \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. \subsecidx{plotclip}$(w)$: \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. \subsecidx{plotcolor}$(w,c)$: \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. \subsecidx{plotcopy}$(\var{sourcew},\var{destw},\var{dx},\var{dy},\{\fl=0\})$: \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 \subsecidx{plotcursor}$(w)$: \label{se:plotcursor}give as a 2-component vector the current (scaled) position of the virtual cursor corresponding to the rectwindow $w$. \subsecidx{plotdraw}$(\var{list}, \{\fl=0\})$: \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 \subsecidx{ploth}$(X=a,b,\var{expr},\{\var{flags}=0\},\{n=0\})$: \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 15 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$. \subsecidx{plothraw}$(\var{listx},\var{listy},\{\fl=0\})$: \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}. \subsecidx{plothsizes}$(\{\fl=0\})$: \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 \subsecidx{plotinit}$(w,\{x\},\{y\},\{\fl=0\})$: \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 \subsecidx{plotkill}$(w)$: \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. \subsecidx{plotlines}$(w,X,Y,\{\fl=0\})$: \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. \subsecidx{plotlinetype}$(w,\var{type})$: \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. \subsecidx{plotmove}$(w,x,y)$: \label{se:plotmove}move the virtual cursor of the rectwindow $w$ to position $(x,y)$. \subsecidx{plotpoints}$(w,X,Y)$: \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)$. \subsecidx{plotpointsize}$(w,\var{size})$: \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. \subsecidx{plotpointtype}$(w,\var{type})$: \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. \subsecidx{plotrbox}$(w,\var{dx},\var{dy})$: \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. \subsecidx{plotrecth}$(w,X=a,b,\var{expr},\{\fl=0\},\{n=0\})$: \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. \subsecidx{plotrecthraw}$(w,\var{data},\{\var{flags}=0\})$: \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. \subsecidx{plotrline}$(w,\var{dx},\var{dy})$: \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). \subsecidx{plotrmove}$(w,\var{dx},\var{dy})$: \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). \subsecidx{plotrpoint}$(w,\var{dx},\var{dy})$: \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)$. \subsecidx{plotscale}$(w,\var{x1},\var{x2},\var{y1},\var{y2})$: \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$ ($x2b$. $a$ and $b$ must be in $\R$. \subsecidx{fordiv}$(n,X,\var{seq})$: \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 \subsecidx{forell}$(E,a,b,\var{seq})$: \label{se:forell}evaluates \var{seq}, where the formal variable $E$ ranges through all elliptic curves of conductors from $a$ to $b$. Th \tet{elldata} database must be installed and contain data for the specified conductors. \synt{forell}{void *data, long (*call)(void*,GEN), GEN a, GEN b}. \subsecidx{forprime}$(X=a,b,\var{seq})$: \label{se:forprime}evaluates \var{seq}, where the formal variable $X$ ranges over the prime numbers between $a$ to $b$ (including $a$ and $b$ if they are prime). More precisely, the value of $X$ is incremented to the smallest prime strictly larger than $X$ at the end of each iteration. Nothing is done if $a>b$. Note that $a$ and $b$ must be in $\R$. \bprog f(N) = { forprime(p = 2, N, print(p); if (p == 3, p = 6); ) } ? f(12) 2 3 7 11 @eprog \subsecidx{forstep}$(X=a,b,s,\var{seq})$: \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 $ax^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 \synt{genapply}{void *E, GEN (*fun)(void*,GEN), GEN a}. \subsecidx{default}$(\{\var{key}\},\{\var{val}\})$: \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}. \subsecidx{error}$(\{\var{str}\}*)$: \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} \subsecidx{extern}$(\var{str})$: \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. \subsecidx{externstr}$(\var{str})$: \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. \subsecidx{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}{}. \subsecidx{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}{}. \subsecidx{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}{}. \subsecidx{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. The library syntax is \fun{long}{gettime}{}. \subsecidx{global}$(\var{list} \var{of} \var{variables})$: \label{se:global}obsolete. Scheduled for deletion. % \syn{NO} \subsecidx{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). \subsecidx{install}$(\var{name},\var{code},\{\var{gpname}\},\{\var{lib}\})$: \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 argument code \var{code} (see the Libpari Manual for an explanation of those). If \var{lib} is omitted, uses \kbd{libpari.so}. If \var{gpname} is omitted, uses \var{name}. This function is useful for adding custom functions to the \kbd{gp} interpreter, or picking useful functions from unrelated libraries. For instance, it makes the function \tet{system} obsolete: \bprog ? install(system, vs, sys, "libc.so") ? sys("ls gp*") gp.c gp.h gp_rl.c @eprog But it also 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 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 it the latter has been recompiled. \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, i.e.~a major internal blunder (this should never happen with a dynamically linked executable). Hence, if you intend to use this function, please check first on some harmless example such as the ones above that it works properly on your machine. \subsecidx{kill}$(\var{sym})$: \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}. \subsecidx{print}$(\{\var{str}\}*)$: \label{se:print}outputs its (string) arguments in raw format, ending with a newline. %\syn{NO} \subsecidx{print1}$(\{\var{str}\}*)$: \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} \subsecidx{printf}$(\var{fmt},\{x\}*)$: \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} \subsecidx{printtex}$(\{\var{str}\}*)$: \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} \subsecidx{quit}$(\{\var{status} = 0\})$: \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)}). \subsecidx{read}$(\{\var{filename}\})$: \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. \subsecidx{readvec}$(\{\var{filename}\})$: \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. \subsecidx{select}$(f, A)$: \label{se:select}Given a vector, list or matrix \kbd{A} and a \typ{CLOSURE} \kbd{f}, 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 following function lists the elements in $(\Z/N\Z)^*$: \bprog ? invertibles(N) = select(x->gcd(x,N) == 1, vector(N,i,i)) @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}. \subsecidx{setrand}$(n)$: \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}. \subsecidx{system}$(\var{str})$: \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. \subsecidx{trap}$(\{e\}, \{\var{rec}\}, \var{seq})$: \label{se:trap}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 (gdiver, 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{alarmer}: alarm time-out \kbd{archer}: not available on this architecture or operating system \kbd{errpile}: the PARI stack overflows \kbd{gdiver}: division by 0 \kbd{impl}: not yet implemented \kbd{invmoder}: impossible inverse modulo \kbd{overflower}: all forms of arithmetic overflow, including length or exponent overflow (when a larger value is supplied than the implementation can handle). \kbd{syntaxer}: syntax error \kbd{talker}: miscellaneous error \kbd{typeer}: wrong type \kbd{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}. \subsecidx{type}$(x)$: \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. \subsecidx{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 a more precise version string, e.g.~\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, 0, "git-2cce227"] \\ development @eprog In particular the first line of the gp introductory message can be essentially emulated by \bprog v = version(); n = Str(v[1], ".", v[2], ".", v[3]); s = if (#v > 3, v[4], ""); print("GP/PARI CALCULATOR Version ", n, " (", s, ")"); @eprog\noindent If you \emph{are} working with many development versions of PARI/GP, the last component can be profitably included in the name of your logfile, for instance. The library syntax is \fun{GEN}{pari_version}{}. \subsecidx{warning}$(\{\var{str}\}*)$: \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} \subsecidx{whatnow}$(\var{key})$: \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). \subsecidx{write}$(\var{filename},\{\var{str}\}*)$: \label{se:write}writes (appends) to \var{filename} the remaining arguments, and appends a newline (same output as \kbd{print}). %\syn{NO} \subsecidx{write1}$(\var{filename},\{\var{str}\}*)$: \label{se:write1}writes (appends) to \var{filename} the remaining arguments without a trailing newline (same output as \kbd{print1}). %\syn{NO} \subsecidx{writebin}$(\var{filename},\{x\})$: \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}). 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. User functions, installed functions and history objects can not be saved via this function. 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}. \subsecidx{writetex}$(\var{filename},\{\var{str}\}*)$: \label{se:writetex}as \kbd{write}, in \TeX\ format. %\syn{NO} %SECTION: programming/specific \section{GP defaults} \label{se:gp_defaults} This section documents the GP defaults \subsecidx{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}. \subsecidx{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. \subsecidx{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 $\bullet$ the keyword \kbd{no} (use the default color, usually black on transparent background) \noindent $\bullet$ an integer between 0 and 15 corresponding to the aforementioned colormap \noindent $\bullet$ 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). \subsecidx{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 favourite 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}. \subsecidx{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=}). \subsecidx{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). \subsecidx{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). \subsecidx{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). \subsecidx{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 defaut 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 defaut value is \kbd{0}. \subsecidx{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. \subsecidx{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{"antique white"} represent the same color. RGB codes are a little 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"}]. \subsecidx{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]}. \subsecidx{help}: \label{se:def,help}name of the external help program which will be used 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 local of the \kbd{gphelp} script. \subsecidx{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). \subsecidx{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}. \subsecidx{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}. \subsecidx{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}. \subsecidx{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{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 defaut value is \kbd{0}. This value will change to $1$ (set) in the next major version. \subsecidx{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: $\bullet$ \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. $\bullet$ \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. $\bullet$ \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}). \subsecidx{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. \subsecidx{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. \subsecidx{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"}. \subsecidx{primelimit}: \label{se:def,primelimit}\kbd{gp} precomputes a list of all primes less than \kbd{primelimit} at initialization time. These are used by many arithmetic functions, usually for trial division purposes. If you do not plan to invoke any of them, you can just set this to 1. The maximal value is a little less than $2^{32}$ (resp $2^{64}$) on a 32-bit (resp.~64-bit) machine. Since almost all arithmetic functions eventually require some table of prime numbers, PARI currently guarantees that the first 6547 primes, up to and including 65557, are precomputed, even if \kbd{primelimit} is $1$. The default value is \kbd{500k}. \subsecidx{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 defaut value is \kbd{""}. \subsecidx{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"}. \subsecidx{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}. \subsecidx{realprecision}: \label{se:def,realprecision} \subsecidx{realprecision} : the number of significant digits and, at the same time, the number of printed digits of real numbers (see~\b{p}). Note that PARI internal precision works on a word basis (32 or 64 bits), hence may not coincide with the number of decimal digits you input. For instance to get 2 decimal digits you need one word of precision which, on a 32-bit machine, actually gives you 9 digits ($9 < \log_{10}(2^{32}) < 10$): \bprog ? default(realprecision, 2) realprecision = 9 significant digits (2 digits displayed) @eprog The default value is \kbd{28}, resp.~\kbd{38} on a 32-bit, resp~.64-bit, machine. \subsecidx{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}. \subsecidx{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}. \subsecidx{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}. \subsecidx{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}. \subsecidx{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}. \subsecidx{timer}: \label{se:def,timer}this toggle is either 1 (on) or 0 (off). If on, every instruction sequence (anything ended by a newline in your input) is timed, to some accuracy depending on the hardware and operating system. The time measured is the user \idx{CPU time}, \emph{not} including the time for printing the results (see \kbd{\#} and \kbd{\#\#}). The default value is \kbd{0}. %SECTION: default \vfill\eject pari-2.5.5/doc/develop.tex0000644000175000017500000004332212147140046014034 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. \item \kbd{z[2]} points to a \typ{STR} which hold the opcodes. \item \kbd{z[3]} points to a \typ{VECSMALL} which hold the operands of the opcodes. \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. \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. 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. 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. \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{Otherwise undocumented global variables} \tet{PARI_SIGINT_block}: set this to a non-zero value if you want to block the \kbd{SIGINT} signal in a critical part of your code. We use it before calling \kbd{malloc}, \kbd{free} and such. (Because \kbd{SIGINT} is non-fatal for us, and we don't want to leave the system stack in an inconsistent state.) \tet{PARI_SIGINT_pending}: if this is non-zero, then a \kbd{SIGINT} was blocked. Take action as appropriate. \section{Finite fields and 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); GEN (*rand)(void*); int (*cmp)(GEN, GEN); int (*equal1)(GEN); }; @eprog \kbd{mul(E,x,y)} returns the product $xy$. \kbd{pow(E,x,n)} returns $x^n$ ($n$ integer, possibly negative or zero). \kbd{rand(E)} returns a random element in the group. \kbd{cmp(x,y)} implements a total ordering on the group elements (return value $-1$, $0$ or $1$). \kbd{equal1(x)} returns one if $x$ is the neutral element in the group, and zero otherwise. A group is thus described by a \kbd{const bb\_struct} 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$. 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. \fun{GEN}{gen_plog}{GEN x, GEN g, GEN N, void *E, const struct bb_group, GEN easy(void*, GEN, GEN, GEN)} \hbadness 10000 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}. 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. \misctitle{FIXME} More generally, one should compute the minimal polynomial of $x$ and restrict to its field of definition. \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, GEN easy(void *E, GEN, GEN, GEN)} \hbadness 10000 Generic Pohlig-Hellman algorithm. Assuming that $g$ has order $N$, compute an integer $k$ such that $g^k = x$. This requires $O(p^{1/2+\epsilon})$ group operations, where $p$ is the largest prime divisor of $N$, and uses an auxiliary table containing $O(\sqrt{p})$ group elements. \kbd{easy} is as in \kbd{gen\_plog}. \fun{GEN}{gen_eltorder}{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. \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{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, GEN g, long flag} as \tet{print0}, using output context \kbd{out}. \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(user,)} \fun{void}{warning0}{GEN g}. Use \kbd{pari\_warn(user,)} \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} latter 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. \subsec{Function related to the GP parser} The GP parser can generate an opcode saving the current lexical context (pairs made of a lexical variable name and its value) in a \kbd{GEN}, called \kbd{pack} in the sequel. These can be used from debuggers (e.g. gp's break loop) to track values of lexical variable. Indeed, lexical variables have disappeared from the compiled code, only their values in a given scope exist (on some value stack). Provided the parser generated the proper opcode, there remains a trace of lexical variable names and everything can still be unravelled. \fun{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. \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 Go to the relevant \kbd{Oxxx} directory, then \bprog patch -p0 < 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.) \vfill\eject \input index\end pari-2.5.5/doc/pdfmacs.tex0000644000175000017500000001206711636712103014016 0ustar billbill% $Id$ % 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.5.5/doc/index.tex0000644000175000017500000000643011636712103013505 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.5.5/doc/appb.tex0000644000175000017500000000215511636712103013320 0ustar billbill% $Id$ % 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.5.5/doc/usersch5.tex0000644000175000017500000125502112147140046014141 0ustar billbill% $Id$ % 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. \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. \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. \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 stackbase is \kbd{NULL}, disable the check, else set the base address to 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} 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 \kbd{SIGINT} is raised. By default, raises \bprog pari_err(talker, "user interrupt"); @eprog \doc{cb_pari_err_recover}{extern void (*cb_pari_err_recover)(long)} initialized to \kbd{pari\_exit()}. This call-back must not return. This call-back 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. \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{GEN}{pari_add_hist}{GEN x} adds \kbd{x} as the last history entry. \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{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{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} returns the degree of \typ{POL}~\kbd{x}, \emph{assuming} its leading coefficient is non-zero (an exact $0$ is impossible, but an inexact $0$ is allowed). By convention the degree of an exact $0$ polynomial is $-1$. If the leading coefficient of \kbd{x} is $0$, the result is undefined. \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}{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}) \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 the constant term 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 the leading term of \typ{POL}~\kbd{x}. This may be an inexact $0$. \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{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*}{stackmalloc}{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. \noindent Objects allocated through these last two 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. \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{void}{gunclone}{GEN x} deletes a clone. 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. \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}{char *s}: 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{Interlude: parser codes} \label{se:gp.interface} A \idx{parser code} 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 $\bullet$ 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 \kbd{GEN}. Here it is allowed to directly return a component of the input (obviously \cr \+&&\quad not suitable for \kbd{gerepileupto}). Used for member functions, to avoid costly copies.\cr \noindent$\bullet$ Mandatory arguments, appearing in the same order as the input arguments they describe: % \+& \kbd{G} & \kbd{GEN}\cr \+& \kbd{\&}& \kbd{*GEN}\cr \+& \kbd{L} & long {\rm (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{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 \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$\bullet$ 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 \noindent $\bullet$ Syntax requirements, used by functions like \kbd{for}, \kbd{sum}, etc.: % \+& \kbd{=} & separator \kbd{=} required at this point (between two arguments)\cr \noindent$\bullet$ Optional arguments and default values: % \+& \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{s*} code reads all remaining arguments in \tev{string context} (see \secref{se:strings}), and sends a (\kbd{NULL}-terminated) list of \kbd{GEN*} pointing to these. 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 a \kbd{GEN *g = \obr \&a, \&b, \&c, NULL\cbr}, 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 \+&\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}& 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, char *gpname, 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. \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_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_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 \typ{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 a \idx{primitive root} modulo \kbd{p}, assuming \kbd{p} is prime. \fun{ulong}{pgener_Zl}{ulong p} returns a primitive root modulo $p^k$, $k > 1$, assuming $p$ is an odd prime. On a 64-bit machine, this function may fail and raise an exception, if $p > 2^{63}$; namely when $g := \kbd{pgener\_Fl}(p)$ is not a primitive element and $g + p$ no longer fits in an \kbd{ulong}. (It turns out that this cannot happen on a 32-bit architecture.) Use \kbd{gener\_Fp} if this is a problem. \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}. \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{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)$. \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{Valuations} \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 the highest exponent $e$ such that $\kbd{p}^{e}$ divides~\kbd{x}. The quotient $\kbd{x}/\kbd{p}^{e}$ is returned in~\kbd{*r}. In particular, if \kbd{p} is a prime, this returns the valuation at \kbd{p} of~\kbd{x}, and \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 the ``valuation''. \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_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_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{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} \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} adds \kbd{x} by \kbd{y}. \fun{GEN}{subuu}{ulong x, ulong 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}{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}{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}. \subsec{Exact division and divisibility} \fun{void}{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{void}{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. 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, long *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}{udivui_rem}{ulong s, GEN y, ulong *rem} computes the Euclidean quotient and remainder of the $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}{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$ modulo $2^\B$. This is meant to be used for tiny $n$, where in fact $x^n$ fits into an \kbd{ulong}. \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$. \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}{uissquareall}{ulong n, ulong *sqrtn} as \kbd{Z\_issquareall}, for an \kbd{ulong} operand \kbd{n}. \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, ulong *pminp, ulong cutoff} $x > 0$ is an integer and we look for the smallest prime $p \geq \max(11,\kbd{*pminp})$ such that $x = n^p$. (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 $p$ and set \kbd{*ptn} to $n$. \kbd{*pminp} is updated to $p$, so that we may immediately recall the function with the same parameters after setting $x = \kbd{*ptn}$. \subsec{Factorization} \fun{GEN}{Z_factor}{GEN n} factors the \typ{INT} \kbd{n}. The ``primes'' in the factorization are actually strong pseudoprimes. \fun{int}{is_Z_factor}{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. \fun{long}{Z_issquarefree}{GEN x} 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}{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}{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}{core}{GEN n} unique squarefree integer $d$ dividing $n$ such that $n/d$ is a square. \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}$. \fun{GEN}{factor_pn_1}{GEN p, long n} returns the factorization of $p^n-1$, where $p$ is prime and $n$ is a positive integer. \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}{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)}$. \subsec{Primality and compositeness tests} \fun{int}{uisprime}{ulong p}, returns $1$ if \kbd{p} is a prime number and $0$ otherwise. \fun{ulong}{uprimepi}{ulong n}, returns the number of primes $p\leq n$. \fun{ulong}{unextprime}{ulong n}, returns the smallest prime $\geq n$. Return $0$ if it cannot be represented as an \kbd{ulong} (bigger than $2^{64} - 59$ or $2^{32} - 5$ depending on the word size). \fun{ulong}{uprime}{long n} returns the $n$-th prime, assuming it belongs to the precomputed prime table. Error otherwise. \fun{GEN}{prime}{long n} same as \kbd{utoi(uprime(n))}. \fun{GEN}{primes_zv}{long m} returns the $m$-th first primes, in a \typ{VECSMALL}, assuming they belong to the precomputed prime table. Error 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{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_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_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=1 \pmod{p}$. Return an integer $e$ such that $a^e=g \pmod{p}$. If $e$ does not exists, the result is currently undefined. \fun{GEN}{Fp_order}{GEN a, GEN ord, GEN p} returns the order of the \typ{Fp} \kbd{a}. If \kbd{ord} is non-\kbd{NULL}, it is assumed that \kbd{ord} is a multiple of the order of \kbd{a}, either as a \typ{INT} or a factorization matrix. \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}{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 a primitive root modulo \kbd{p}, assuming \kbd{p} is prime. \fun{GEN}{pgener_Zp}{GEN p} returns a 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{GEN}{pgener_Fp_local}{GEN p, GEN L}, \kbd{L} being a vector of primes dividing $p - 1$, returns an integer $x$ 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. \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_GG}{GEN (*f)(GEN,GEN), GEN x, GEN n} If $x$ and $n$ are both vector types, expand $x$ first, then $n$. \fun{GEN}{map_proto_lGG}{long (*f)(GEN,GEN), GEN x, GEN n} \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}{eulerphiu}{ulong n}, Euler's totient function of $n$. \fun{GEN}{divisorsu}{ulong n}, returns the divisors of $n$ in a \typ{VECSMALL}, sorted by increasing order. \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. \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{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 know 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}, \kbd{FqM}} 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$. An \kbd{FqM} is a matrix 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}). \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. 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_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} \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_invimage}{GEN m, GEN v, GEN p} as \kbd{inverseimage} \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} but returns a \typ{VECSMALL} \fun{GEN}{FpM_suppl}{GEN x, GEN p} as \kbd{suppl} \subsubsec{\kbd{Fq}-linear algebra} \fun{GEN}{FqM_gauss}{GEN a, GEN b, GEN T, GEN p} as \kbd{gauss} \fun{GEN}{FqM_ker}{GEN x, GEN T, GEN p} as \kbd{ker} \fun{GEN}{FqM_suppl}{GEN x, GEN T, GEN p} as \kbd{suppl} \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}{Flm_copy}{GEN x} returns a copy of \kbd{x}. \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{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{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{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_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} \fun{GEN}{Flm_indexrank}{GEN x, ulong p} \fun{GEN}{Flm_inv}{GEN x, ulong p} \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{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{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}{zero_F2v}{long n} creates a \kbd{F2v} with \kbd{n} components set to $0$. \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_ZC}{GEN x} \fun{GEN}{ZV_to_F2v}{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{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{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}{FlxqM_ker}{GEN x, GEN T, ulong p} \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}, preferrably 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). \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_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_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}{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_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_invMontgomery}{GEN T, GEN p}, returns the Montgomery 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_rem_Montgomery}{GEN x, GEN mg, GEN T, GEN p}, returns \kbd{x} modulo \kbd{T}, assuming that $\deg x\leq 2\*(\deg{T} - 1)$ where \kbd{mg} is the Montgomery inverse of \kbd{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}{FpXY_eval}{GEN Q, GEN y, GEN x, GEN p} $Q$ 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$ 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{FpY} $Q(x,Y)$. \fun{GEN}{FpXY_evaly}{GEN Q, GEN y, GEN p, long vy} $Q$ 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{FpX} $Q(X,y)$. \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_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.) \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. \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_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{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_order}{GEN a, GEN ord, GEN T, GEN p} returns the order of the \typ{FpXQ} \kbd{a}. If \kbd{o} is non-\kbd{NULL}, it is assumed that \kbd{o} 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{GEN}{FpXQ_sqrtn}{GEN x, GEN n, GEN T, GEN p, GEN *zn} returns an \kbd{n}-th root of $\kbd{x}$. Return \kbd{NULL} if \kbd{x} is not an \kbd{n}-th power residue. Otherwise, if \kbd{zn} is non-\kbd{NULL} set it to a primitive \kbd{n}-th root of the unity. Assumes that \kbd{T} is irreducible mod \kbd{p}. \fun{GEN}{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_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}{FqV_inv}{GEN x, GEN T, GEN p} $x$ being a vector of \typ{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_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_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}{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}{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}} Contrary to what the name implies, an \kbd{FpXX} is a \typ{POL} whose coefficients are either \typ{INT}s or \typ{FpX}s. This reduces memory overhead at the expense of consistency. \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_Fp_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{FpXX}~\kbd{x} by the \kbd{Fp}~\kbd{y}. \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_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_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. \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}{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}{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}{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}{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}{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}{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]})$. \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}$. \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 p, GEN T}. 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 p, GEN T}. 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}{FqX_nbfact}{GEN u, GEN T, GEN p}. Assumes \kbd{p} is prime and \kbd{T} irreducible in $\F_p[X]$. \fun{long}{FqX_nbroots}{GEN f, GEN T, GEN p} Assumes \kbd{p} is prime and \kbd{T} irreducible in $\F_p[X]$. \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{Basic operations} \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}{padic_to_Fl}{GEN x, ulong p} special case of \tet{Rg_to_Fl}, for a $x$ a \typ{PADIC}. \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{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_Fl_mul_to_monic}{GEN y, ulong x, ulong p} returns $y*x$ assuming the result is monic of the same degree as $y$ (in particular $x\neq 0$). \fun{GEN}{Flx_sqr}{GEN x, ulong p} \fun{GEN}{Flx_divrem}{GEN x, GEN y, ulong p, GEN *pr} \fun{GEN}{Flx_div}{GEN x, GEN y, ulong p} \fun{GEN}{Flx_rem}{GEN x, GEN y, ulong p} \fun{GEN}{Flx_deriv}{GEN z, ulong p} \fun{GEN}{Flx_gcd}{GEN a, GEN b, ulong p} returns a (not necessarily monic) greatest common divisor of $x$ and $y$. \fun{GEN}{Flx_halfgcd}{GEN x, GEN y, GEN p} returns a two-by-two \kbd{FlxM} $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}{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_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 small $p$ and small degrees ! \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_invMontgomery}{GEN T, ulong p}, returns the Montgomery 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_rem_Montgomery}{GEN x, GEN mg, GEN T, ulong p}, returns \kbd{x} modulo \kbd{T}, assuming that $\deg x\leq 2\*(\deg{T} - 1)$ where \kbd{mg} is the Montgomery inverse of \kbd{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}{FlxYqQ_pow}{GEN x, GEN n, GEN S, GEN T, ulong p}, as \kbd{FpXYQQ\_pow}. \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_inflate}{GEN P, long d} returns $P(X^d)$. \fun{GEN}{FlxV_Flc_mul}{GEN V, GEN W, ulong p}, as \kbd{FpXV\_FpC\_mul}. \fun{int}{Flx_is_squarefree}{GEN z, ulong p} \fun{long}{Flx_nbfact}{GEN z, ulong p}, as \kbd{FpX\_nbfact}. \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{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}{Flx_nbroots}{GEN f, ulong p}, as \kbd{FpX\_nbroots}. \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{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_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}{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. Assumes 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_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}{FlxX_add}{GEN P, GEN Q, ulong p} \fun{GEN}{FlxY_Flx_div}{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} \subsec{\kbd{FlxqX}} See \kbd{FpXQX} operations. \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_red}{GEN z, GEN T, ulong p} \fun{GEN}{FlxqX_normalize}{GEN z, GEN T, ulong p} \fun{GEN}{FlxqX_sqr}{GEN x, 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_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). \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_pow}{GEN x, GEN n, GEN S, GEN T, ulong p} \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 sv} \fun{GEN}{ZX_to_F2x}{GEN x} \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{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_extgcd}{GEN a, GEN b, GEN *ptu, GEN *ptv} \fun{GEN}{F2x_gcd}{GEN a, GEN b} \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{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_sqrt}{GEN a, GEN T} \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} \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}{FpM_to_mod}{GEN z, GEN p}, \kbd{z} a \kbd{ZM}. Returns \kbd{z * Mod(1,p)}, with \typ{INTMOD} coefficients. \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}. 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, GEN qp, 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}, and the product $\kbd{qp} = \kbd{p} \cdot \kbd{q}$, this function updates \kbd{*H} so that it also becomes congruent to $(\kbd{Hp}, \kbd{p})$. 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, GEN qp, 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, GEN qp, 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{int}{ratlift}{GEN x, GEN m, GEN amax, GEN bmax, GEN *a, GEN *b}. Calls \tet{Fp_ratlift} after explicitly checking all preconditions. \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}. \subsec{Hensel lifts} \fun{GEN}{Zp_sqrtlift}{GEN a, GEN S, 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}{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{Fq}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 simple root mod $p$. Return a \typ{INT} which are the root of $f$ mod $p^e$ congruent to $a$ mod $p$. \fun{GEN}{ZpX_liftroots}{GEN f, GEN S, GEN q, 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 roots in the unramified extension of $\Q_p$ with residue field $\F_p[Y]/(T)$. \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{GEN}{ZpX_gcd}{GEN f,GEN g, 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 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. \subsec{Conversions involving single precision objects} \subsubsec{To single precision} \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}{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}{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}{ZM_to_Flm}{GEN x, ulong p} reduce \kbd{ZM}~\kbd{x} modulo \kbd{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_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}{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. \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} \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}{matid_Flm}{long n} returns an \kbd{Flm} which is an $n \times n$ identity matrix. \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}{Fly_to_FlxY}{GEN a, long sv} convert coefficients of \kbd{a} to constant \kbd{Flx} in variable $v$. \subsubsec{Miscellaneous involving F2} \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 polynomials to get an \kbd{F2m} with \kbd{n} rows. \section{Arithmetic on elliptic curve over a finite field in simple form} \subsec{\kbd{FpE}} Let $p$ a prime number and $E$ the elliptic curve given by the equation $E:y^2=x^3+a_4\*x+a_6$. A \kbd{FpE} is a point of $E(\F_p)$. \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}{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_tatepairing}{GEN P, GEN Q, GEN m, GEN a4, GEN p} returns the reduced Tate pairing of the point of $m$-torsion $P$ and the point $Q$. \fun{GEN}{FpE_weilpairing}{GEN Q, GEN Q, GEN m, GEN a4, GEN p} returns the Weil pairing of the points of $m$-torsion $P$ and $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 A, 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}{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_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{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}{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_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{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 computed and 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 \typ{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{long}{zv_content}{GEN x} returns the gcd of the entries of $x$. \fun{long}{zv_prod}{GEN x} returns the product of all the components of~\kbd{x} (assumes no overflow occurs). \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{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}. \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. \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}{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_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,]$ is $y$ is a row matrix $1\times n$, error otherwise. \fun{GEN}{RgM_RgV_mul}{GEN x, GEN y} returns $x\times y[,1]$ is $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}{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_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}. \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}{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} \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). \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_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_fpnorml2}{GEN x, long prec} returns (a stack-clean variant of) \bprog gnorml2( RgM_gtofp(x, prec) ) @eprog 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}{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}. \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}, \kbd{QX}} \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{void}{RgX_check_ZXY}{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}{ZX_copy}{GEN x,GEN p} returns a copy of \kbd{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} are equal 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_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_Z_divexact}{GEN x, GEN y} returns $x/y$ assuming all divisions are exact. \fun{GEN}{ZXV_Z_mul}{GEN x,GEN y} multiplies the vector of \kbd{ZX} \kbd{x} by the integer \kbd{y}. \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}{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{long}{ZX_valrem}{GEN P, GEN *z} as \kbd{RgX\_valrem}, but assumes \kbd{P} has \typ{INT} coefficients. \fun{long}{ZX_val}{GEN P} as \kbd{RgX\_val}, but assumes \kbd{P} has \typ{INT} coefficients. \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{GEN}{QX_gcd}{GEN x,GEN y} returns a gcd of the \kbd{QX} $x$ and $y$. \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. (Leaves small objects on the stack. Suitable but inefficient for \kbd{gerepileupto}.) \fun{long}{ZX_max_lg}{GEN x} returns the effective length of the longest component in $x$. \fun{long}{ZXY_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}{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_deriv}{GEN x} returns the derivative of \kbd{x}. \fun{GEN}{ZX_disc}{GEN T} returns the discriminant of the \kbd{ZX} \kbd{T}. \fun{GEN}{QX_disc}{GEN T} returns the discriminant of the \kbd{QX} \kbd{T}. \fun{int}{ZX_is_squarefree}{GEN T} returns $1$ if the \kbd{ZX}~\kbd{T} is squarefree, $0$ otherwise. \fun{GEN}{ZX_factor}{GEN T} returns the factorization of the primitive part of \kbd{T} over $\Q[X]$ (the content is lost). \fun{GEN}{QX_factor}{GEN T} as \kbd{ZX\_factor}. \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}. \fun{GEN}{ZX_resultant}{GEN A, GEN B} returns the resultant of the \kbd{ZX}~\kbd{A} and \kbd{B}. \fun{GEN}{QX_resultant}{GEN A, GEN B} returns the resultant of the \kbd{QX}~\kbd{A} and \kbd{B}. \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}{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_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}$. \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$). \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}. \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{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_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_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_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{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{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{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_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-zero 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_renormalize}{GEN x} remove leading terms in \kbd{x} which are equal to (necessarily inexact) zeros. \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_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} as \kbd{RgX\_RgXQ\_eval(f, x, T)}, assuming $V$ was output by \kbd{RgXQ\_powers(x, n, T)}. \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}{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}{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}{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} \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. \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}{RgX_to_RgV}{GEN x, long N} converts the \typ{POL}~\kbd{x} to a \typ{COL}~\kbd{v} with \kbd{N} components. Other types than \typ{POL} are allowed for \kbd{x}, which is then considered as a constant polynomial. 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}{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}{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} coefficients) to $P(\kbd{pol\_x[w]},u)$, assuming \kbd{n} is an upper bound for $\deg_v(\kbd{P})$. \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}{gtoser}{GEN x, long v} converts the object~\kbd{x} into a \typ{SER} with main variable number~\kbd{v}. \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. \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 + b \kbd{pol\_x}(v)$ \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}{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. \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}{mkcolcopy}{GEN x} creates a 1-dimensional \typ{COL} containing \kbd{x}. \fun{GEN}{mkmatcopy}{GEN x} creates a 1-by-1 \typ{MAT} containing \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}{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}{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}{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}{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]$. \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}{deg1pol_shallow}{GEN a, GEN b,long v} returns the degree 1 \typ{POL} $a + b \kbd{pol\_x}(v)$ \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}{ggval}{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 the sign ($-1$, 0 or 1) of $\kbd{x}-\kbd{y}$). \fun{long}{lexcmp}{GEN x, GEN y} comparison of \kbd{x} with \kbd{y} for the lexicographic ordering. \fun{int}{gcmpX}{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}. \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_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}. \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 GCD of \kbd{x} and~\kbd{y}, and puts (the addresses of) objects $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{GEN}{Q_abs}{GEN x} absolute value of the \typ{INT} or \typ{FRAC}~\kbd{x}. \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$ \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. \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 (*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{leftright_pow}. \fun{GEN}{leftright_pow_fold}{GEN x, GEN n, void *D, F1 sqr, F1 msqr} as \tet{gen_pow}, \kbd{mul} being replaced by \kbd{msqr}, with \kbd{msqr(D, $y$)} returning $xy^2$. In particular \kbd{D} must implicitly contain $x$. \fun{GEN}{leftright_pow_u_fold}{GEN x, ulong n, void *D, F1 sqr, F1 msqr}, see the previous \tet{leftright_pow_fold} \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} 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 $M$ has 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}{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). \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{Polynomial and power series} \fun{GEN}{derivser}{GEN x} returns the derivative 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{long}{degree}{GEN x} returns \kbd{poldegree(x, -1)}, the degree of \kbd{x} with respect to its main variable. \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-zero 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]$). \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{GEN}{FF_p_i}{GEN a} shallow version of \kbd{FF\_p}. \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_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{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\*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_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 *zetan} 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}. \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}{mpexp1}{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{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}. \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}{exp_Ir}{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{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}. \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)} \fun{GEN}{Qp_sqrtn}{GEN x, GEN n, GEN *z} shortcut for \kbd{gsqrtn(x, n, z, /*ignored*/prec)} \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}{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 even \idx{Bernoulli} numbers $B_0,\dots,B_{2n-2}$ as \typ{REAL}s of precision \kbd{prec}. \fun{GEN}{bern}{long i} is a macro returning the \idx{Bernoulli} number $B_{2i}$ at precision \kbd{prec}, assuming that \kbd{mpbern(n, prec)} was called previously with $n > i$. The macro does not check whether $0 \leq i < n$. If cached Bernoullis were initialized to a larger accuracy than desired, use e.g.~\kbd{rtor(bern(i), prec)}. The following functions use cached data if \kbd{prec} is not too large; 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}{mplog2}{long prec} returns $\log 2$ at precision \kbd{prec}. \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 no \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{stackmalloc}). \fun{char*}{itostr}{GEN x} writes the \typ{INT} $x$ to a \tet{stackmalloc}'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*}{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. \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 defaut 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 defaut 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{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 name returned is \tet{malloc}'ed. \fun{char*}{pari_unique_filename}{const char *s} \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, independently of the PARI stack. 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 */ } hashtable; @eprog\noindent \fun{hashtable*}{hash_create}{ulong size, ulong (*hash)(void*), int (*eq)(void*,void*)}\hfil\break creates a hashtable with enough room to contain \kbd{size} entries. The functions \kbd{hash} and \kbd{eq} will be used to compute the hash value of keys and test keys for equality, respectively. \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; 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 = 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(bugparier,"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, however changing both the address of \kbd{t\_foo} and \kbd{s\_foo} is supported as long as the offset \kbd{\&t\_foo-\&s\_foo} do not change. This allow to create stacks of stacks as follow: \bprog struct foo_s { foo t_foo; pari_stack s_foo; } tt_foo; pari_stack st_foo; stack_init(&st_foo, sizeof(*tt_foo), (void**)&tt_foo); long new_stack(void) { long n = stack_new(&st_foo); struct foo_s *st = tt_foo+n; stack_init(&st->s_foo, sizeof(*st->t_foo), (void**)&st->t_foo); return n; } @eprog When a reallocation of \kbd{tt\_foo} occurs, the offset between the components \kbd{.t\_foo} and \kbd{.s\_foo} does not change. \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}{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}{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}{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[ stack_new(&s_foo) ] = x; @eprog \fun{void}{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 *}{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 **}{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}{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. \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_min}{GEN v} returns the minimum of the elements 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_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{fla} has the same meaning as for \kbd{setsearch}. \newpage \chapter{Functions related to the GP interpreter} \section{Handling closures} \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}{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 immediatly. \subsubsec{Standard wrappers for true closures} Theses 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 immediatly. \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_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_strictmatch}{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). pari-2.5.5/doc/users.tex0000644000175000017500000000162412147140046013536 0ustar billbill% $Id$ % 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 \def\subsectitle#1{% \vskip 0pt plus 45pt\penalty-300 \vskip 6pt plus -42pt minus 3pt \sectionhook\noindent{\bf#1}} % 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.5.5/doc/gphelp.in0000755000175000017500000010340512147140046013465 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(); $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 (-r "$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 (-r $docfile) { $pipe = ""; } else { die "Cannot find $docfile" if (! -r "$docfile.z" && ! -r "$docfile.gz" && ! -r "$docfile.Z" && ! -r "$docfile.bz2"); if (-r "$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 $win32 = ($^O =~ /(cyg|ms)win/); $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 ($win32) { # 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\""; } else { # PDF generic $viewer = "acroread"; } print "displaying \'$F\'."; print "\n" if (!$fromgp); safe_setsid(); 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 (!$apropos && $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); while () { if (/^\\(subsubsec[a-z]*|subsec[a-z]*|section|chapter){$help}/) { $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,\+\$/\$-,+/-,; 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); 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 (@_) { $miss--; s/$/ /; return if ($miss == 0); } } } sub fit_line { my($wi, @a); my($l) = -1; my($rem) = $_[0]; for (@l) { $l2 = $l; $l += ($_ + 1); last if ($l > $rem); $wi++; } $miss = $rem - $l2; 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 format_text { my($last_void) = 0; my($add_stuff) = 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$_"); } elsif (s/^\@0//) # verbatim lines { nl("$indent$_"); } elsif (s/^\@2//) # end verbatim { nl("$indent$_"); $last_void = is_void($_); } elsif (is_void($_)) # line is empty { next if (!$add_stuff); if ($init) { nl(&fit_line($first)); } else { nl("") if (!$last_void); nl("\@[endbold]$indent" . &fit_line($first)); } while (@w) { nl(&fit_line($cols)); } $init = $last_void = $add_stuff = 0; } else { $add_stuff = 1; s/^ +//; @_ = split(/\s+/, $_); for (@_) { s/\Q$tr{nbrk}/ /g; push(@w, $_); # these codes will be replaced by 1 character s/\@\[(obr|cbr|ouml|uuml|agrav|eacute|ldollar|pm|lt|gt|\{|\})]/\@/g; # the rest will be replaced by zero-width characters s/\@\[\w+\]//g; push(@l, length($_)); } } } } # 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,$args); # 1: get the function "prototype" $fun = &get_match($_,'{','}'); # name $fun = &basic_subst($fun); $_ = $remainder; # args as $(x)$ in \subsecidx{sin}$(x)$: if (/^ *\$/) { $args = &basic_subst(&get_match($_,'\$','\$')); $_ = $remainder; } $_ = if (!&basic_subst($_)); # dft value as (...) in \subsecidx{echo} (default \kbd{0}) if (/^ *\(/) { $args .= ' (' . &basic_subst(&get_match($_,'\(','\)')) . ')'; $_ = $remainder; } $args .= ":" if ($args !~ /: *$/ && ($args || $fun !~ /: */)); push(@text, "\@[startbold]$fun\@[endbold]$args"); 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{startbold}$1$tr{endbold}$tr{startpodcode}($2)$tr{endpodcode}/; # 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/\\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/\\(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|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/^\\\+/$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/ *\\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\{([^\}]*)\}/$tr{startbold}* $1$tr{endbold}/g; s/(\\bullet|\\item)/$tr{startbold}*$tr{endbold}/g; s/\\misctitle\{([^\}]*)\}/$tr{startbold}$1.$tr{endbold}/g; s/\\subsec\{([^\}]*)\}/$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/\@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/) { $in_prog = 0; $_ = "\@2" . &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($_); } 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|idx|op)?(?:unix)?\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}([^\n]*):[\n ]/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e; s/\\subsubsec(?:ref|idx|op)?(?: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|idx|op)?(?:unix)?\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}(\S*)\s+/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e; s/\\subsec(?:ref|title|idx|op)?(?: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

/* 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 || typ(b) != t_INT) pari_err(typeer, "extgcd"); 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.5.5/examples/minigp.c0000644000175000017500000000352211636712103014353 0ustar billbill#include #include #include #include #include char * prompt = NULL; 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; } 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); } #define col(a) term_get_color(NULL, a) int main(int argc, char **argv) { 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"}, {NULL,0,NULL,0,NULL,NULL}}; 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); if (!in) break; if (!*in) continue; add_history(in); z = gp_read_str(in); if (z != gnil) { pari_add_hist(z); if (in[strlen(in)-1]!=';') { pari_printf("%s%%%lu = %s",col(c_HIST),pari_nb_hist(),col(c_OUTPUT)); output(z); } } free(in); avma=top; } return 0; } pari-2.5.5/examples/Inputrc0000644000175000017500000000055011636712103014271 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.5.5/examples/squfof.gp0000644000175000017500000000200212147140046014546 0ustar billbill\\ return one non-trivial divisor of n > 1 using Shanks's SQUFOF squfof(n) = { 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), 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.5.5/examples/openmp.c0000644000175000017500000000240511636712103014365 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.5.5/examples/taylor.gp0000644000175000017500000000346712147140046014575 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.); blue = min(max(4*(0.75-x), 0), 1); red = min(max(4*(x-0.25), 0), 1); green= min(max(4*abs(x-0.5)-1, 0), 1); return (floor([red, green, blue]*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 (sin by default), \\ of index first + i*step <= ordlim, for x in [xmin,xmax]. plot_taylor(f = x->sin(x), 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() plot_taylor(x->exp(x),-3,3) plot_taylor(x->besselk(2,x), 1,5) plot_taylor(x->1/(1+x^2), -1.2,1.2) pari-2.5.5/examples/classno.gp0000644000175000017500000000166412147140046014722 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) = { my(q0,sd,t,c, s = 0, q = 1); if (!isfundamental(-d), error("Discriminant not fundamental")); if (!cc, cc = 5); sd = sqrt(d); q0 = exp(-2*Pi/sd); c = -4*Pi/sd; for (n=1, ceil(sd*cc), q *= q0; t = 1/(1-q); s += kronecker(-d,n) * q * t * (1 + c*t*n) ); if (d==3, s *= 3); if (d==4, s *= 2); -2*s; } pari-2.5.5/examples/cl.gp0000644000175000017500000000530712147140046013654 0ustar billbillrgcd(a,b)= { my(r); a = abs(a); b = abs(b); while (b > 0.01, r=a%b; a=b; b=r); a; } f(a,b)= { my(j,n,l,mv,u,vreg,cp,p); n = abs( norm(a + b*t) ); mv = vectorv(li); forprime (p=2, plim, if ((l = valuation(n,p)), n /= p^l; j = ind[p]; cp = v[j][2]; while((a+b*cp)%p, j++; cp = v[j][2] ); mv[j]=l ) ); if (n!=1, return); /* found a relation */ vreg = vectorv(lireg,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 ")"); } global(km,clh,R,nf,areg); clareg(pol, plim=19, lima=50, extra=5)= { my(e,t,r,coreg,lireg,r1,ind,fa,li,co,res,a,b,m,mh,ms,mhs,mreg,mregh); nf=nfinit(pol); pol=nf.pol; t=Mod(x,pol); r=nf.roots; r1=nf.sign[1]; if (nf[4] > 1, /* index: power basis <==> nf[4] = 1 */ error("sorry, the case f>1 is not implemented") ); print("discriminant = " nf.disc ", signature = " nf.sign); lireg = (poldegree(pol) + r1) / 2; /* r1 + r2 */ re=vector(lireg,j, if (j<=r1, real(r[j]) , r[j]) ); ind=vector(plim); v=[]; forprime(p=2,plim, w = factormod(pol,p); e = w[,2]; 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]]]) ) ) ); li=#v; co=li+extra; res=0; print("need " co " relations"); areg=[]~; mreg = m = [;]; a=1; b=1; f(0,1); 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]); print("class number = " clh ", class group = " 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 = vecextract(mregh, Str(".." lireg-1), ".."); R = 0; for(j=lireg-1,coreg, a = matdet(vecextract(mreg1, Str(j-lireg+2 ".." j))); R = rgcd(a,R) ) ) ); print("regulator = " R); } check(lim=200) = { my(r1,r2,pol,z,Res,fa); r1=nf.sign[1]; r2=nf.sign[2]; 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.5.5/examples/contfrac.gp0000644000175000017500000000036011636712103015050 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.5.5/examples/thread.c0000644000175000017500000000327611636712103014345 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.5.5/examples/rho.gp0000644000175000017500000000144111636712103014042 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.5.5/config/0000755000175000017500000000000012212611624012346 5ustar billbillpari-2.5.5/config/has_vsnprintf.c0000644000175000017500000000022211636712103015375 0ustar billbill#include #include main() {} int f(int i,...) { char s[1]; va_list ap; va_start(ap,i); vsnprintf(s,1,"",ap); return 0; } pari-2.5.5/config/get_static0000644000175000017500000000173411636712103014427 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 < /dev/null if test -r $exe; then gmp_version=`env LD_LIBRARY_PATH="$LD_LIBRARY_PATH$dir_sep$gmp" $RUNTEST $exe`; fi if test "$gmp_version" = "unsupported"; then echo "### Your GMP library ABI is unsupported." gmp= fi if test -z "$gmp_version"; then $CC $CFLAGS $extraflag $GMPINCLUDE -o $exe ansi.c $GMPLIBS 2> /dev/null 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 gmp= fi rm -f $exe $exe$exe_suff fi 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.5.5/config/has_ftime.c0000644000175000017500000000020711636712103014453 0ustar billbill# include # include # include int main() { struct tms t; times(&t); return (int)t.tms_utime; } pari-2.5.5/config/has_alarm.c0000644000175000017500000000013611636712103014444 0ustar billbill#include unsigned int (*f)(unsigned int) = alarm; int main(){ return f != alarm; } pari-2.5.5/config/kernel-name0000755000175000017500000000113111636712103014471 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.5.5/config/has_TIOCGWINSZ.c0000644000175000017500000000017211636712103015050 0ustar billbill#include #include #include #include main() { int x = TIOCGWINSZ; } pari-2.5.5/config/has_getrlimit.c0000644000175000017500000000025211636712103015347 0ustar billbill#include #include #include main() { struct rlimit rip; getrlimit(RLIMIT_STACK, &rip); setrlimit(RLIMIT_STACK, &rip); } pari-2.5.5/config/get_include_path0000644000175000017500000000071312147140046015572 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/include/$multipath\ /usr/local/include\ /usr/include\ /opt/include\ /opt/local/include\ /opt/gnu/include\ ";; esac basic_include_path=$incpth pari-2.5.5/config/look0000755000175000017500000000103111636712103013236 0ustar billbill# Look for functions in $list. Return as soon as the first function is found, # defining has_$fun for fun in $list; do if ($CC $CFLAGS has_$fun.c -o $exe $extra_flags > /dev/null 2>&1); then if test -s $exe ; then if test -x $exe -o "$osname" = os2 ; then eval "has_$fun=yes"; echo ..."Found $fun." case "$_has_list" in *has_$fun*);; *) _has_list="$_has_list has_$fun";; esac break fi fi fi; eval "has_$fun=no"; echo ..."I did not find $fun." done rm -f $exe pari-2.5.5/config/get_Qt0000644000175000017500000000166312147140046013524 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` QTLIB="-lQtCore -lQtGui" which_graphic_lib=Qt4 if test -z "$QTDIR"; then QTDIR=`locatedir qt/bin $pth` QTLIB="-lQtCore -lQtGui" which_graphic_lib=Qt4 if test -z "$QTDIR"; then QTDIR=`locatedir qt3/bin $pth` QTLIB="-lqt-mt" which_graphic_lib=Qt if test -z "$QTDIR"; then QTDIR=`locatedir qt2/bin $pth` QTLIB="-lqt" which_graphic_lib=Qt 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.5.5/config/get_X110000644000175000017500000000250612147140046013506 0ustar billbilltdir=$osname-$arch-X11$$ mkdir $tdir; cp Imakefile $tdir; cd $tdir if (xmkmf) >/dev/null 2>&1 && test -f Makefile; then eval `make gp-X11 2> /dev/null | grep -v make` x11pth="$usrlibdir $libdir $usrlibdir/$multiarch $libdir/$multiarch"; fi cd ..; rm -rf $tdir # Check xmkmf answer # X11 -- Headers if test ! -f $Xincroot/X11/Xos.h; then x11pth="\ /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\ /usr/lib/$multiarch\ "; 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 # X11 -- Lib pth=$x11pth lib=X11; . ./locatelib if test -f $Xincroot/X11/Xos.h -a -n "$X11"; then echo ..."Found X11 header files in $Xincroot/X11" test -n "$extralib" && echo ..."Extra Libraries are $extralib" X11_LIBS="-L$X11 -lX11 $extralib" X11_INC="-I$Xincroot" else echo "### X11 not found" X11= fi pari-2.5.5/config/get_head0000644000175000017500000000013211636712103014030 0ustar billbillif (head -n 1 < /dev/null >/dev/null 2>&1); then head='head -n' else head='head -' fi pari-2.5.5/config/ldflags0000755000175000017500000000017511636712103013716 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.5.5/config/get_dlcflags0000644000175000017500000000062611636712103014716 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.5.5/config/objdir0000755000175000017500000000026611636712103013554 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.5.5/config/DOC_Make.SH0000644000175000017500000001002512147140046014144 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 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 users.dvi refcard.ps tutorial.dvi docps: develop.ps libpari.ps refcard.ps tutorial.ps users.ps INSTALL.ps docpdf: develop.pdf libpari.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 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.5.5/config/locatedir0000755000175000017500000000017211636712103014245 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.5.5/config/get_MANIFEST0000755000175000017500000000055412147140046014347 0ustar billbillgit ls-files | grep -v '/$' | grep -v '\.gitignore' | grep -v TODO |grep -v '^Announce\.' # generated files echo Odos/paricfg.h 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.5.5/config/GEN_Make.SH0000644000175000017500000000421611636712103014156 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.5.5/config/get_config_options0000644000175000017500000001730212147140046016155 0ustar billbill# Processing Options dflt_conf_file=pari.cfg fastread=yes config_file= optimization=full target_host= which_graphic_lib=auto readline_enabledp=nil share_prefix= prefix=/usr/local test -n "$GP_INSTALL_PREFIX" && prefix="$GP_INSTALL_PREFIX" while test $# -gt 0; do case "$1" in -l|--load) shift; initfile=$1; cd "$TOP" PATH=.:$PATH; export PATH if test -z "$1";then tmp_host=`$config_dir/arch-osname` arch=`echo "$tmp_host" | sed -e 's/\(.*\)-.*/\1/'` osname=`echo "$tmp_host" | sed -e 's/.*-\(.*\)/\1/'` objdir=O$osname-$arch; initfile=$objdir/$dflt_conf_file; fi if test -d "$initfile"; then initfile="$initfile/pari.cfg" fi if test -r "$initfile"; then . $initfile if test ! -d $objdir; then mkdir $objdir; fi . $config_dir/get_tests # in case the test set have been changed . $config_dir/extract_files exit 0 else echo "Cannot read config file \"$initfile\"." >&2 exit 1 fi;; -p|-prefix) shift; prefix=$1;; --prefix=*|--prefi=*|--pref=*|--pre=*|--pr=*|--p=*) prefix=`echo "$1" | sed -e 's/[-a-z]*=//'`;; --share-prefix=*) share_prefix=`echo "$1" | sed -e 's/[-a-z]*=//'`;; --bindir=*) dfltbindir=`echo "$1" | sed -e 's/[-a-z]*=//'`;; --datadir=*) dfltdatadir=`echo "$1" | sed -e 's/[-a-z]*=//'`;; --includedir=*) dfltincludedir=`echo "$1" | sed -e 's/[-a-z]*=//'`;; --libdir=*) dfltlibdir=`echo "$1" | sed -e 's/[-a-z]*=//'`;; --mandir=*) dfltmandir=`echo "$1" | sed -e 's/[-a-z]*=//'`;; --sysdatadir=*) dfltsysdatadir=`echo "$1" | sed -e 's/[-a-z]*=//'`;; --time=*) timing_fun=`echo "$1" | sed -e 's/[-a-z]*=//'`;; --host=*) target_host=`echo "$1" | sed -e 's/[-a-z]*=//'`;; --kernel=*) kernel=`echo "$1" | sed -e 's/[-a-z]*=//'`;; --tune) tune=yes;; --builddir) dfltobjdir=auto;; --builddir=*) dfltobjdir=`echo "$1" | sed -e 's/[-a-z]*=//'`;; -a|-ask|--ask) fastread=no;; -g) optimization=debugging;; -pg) optimization=profiling;; -h|-help|--help|-\?)error=true;; -v|-verbhelp|--verbhelp)error=verb;; -s|--static) static=y;; -graphic|--graphic) shift; which_graphic_lib=$1;; --graphic=*|--graphi=*|--graph=*|--grap=*|--gra=*|--gr=*|--g=*) which_graphic_lib=`echo "$1" | sed -e 's/[-a-z]*=//'`;; --without-readline|--with-readline=no) without_readline=yes ;; --with-readline) with_readline=yes ;; --with-readline=*) with_readline=`echo "$1" | sed -e 's/[-a-z]*=//'` ;; --with-readline-lib=*) with_readline_lib=`echo "$1" | sed -e 's/[-a-z]*=//'` ;; --with-readline-include=*) with_readline_include=`echo "$1" | sed -e 's/[-a-z]*=//'` ;; --without-gmp|--with-gmp=no) without_gmp=yes ;; --with-gmp) with_gmp=yes ;; --with-gmp=*) with_gmp=`echo "$1" | sed -e 's/[-a-z]*=//'` ;; --with-gmp-lib=*) with_gmp_lib=`echo "$1" | sed -e 's/[-a-z]*=//'` ;; --with-gmp-include=*) with_gmp_include=`echo "$1" | sed -e 's/[-a-z]*=//'` ;; --with-ncurses-lib=*|--with-ncurses=*) with_ncurses_lib=`echo "$1" | sed -e 's/[-a-z]*=//'` ;; --with-qt) with_qt=yes ;; --with-qt=*) with_qt=`echo "$1" | sed -e 's/[-a-z]*=//'` ;; --with-fltk) with_fltk=yes ;; --with-fltk=*) with_fltk=`echo "$1" | sed -e 's/[-a-z]*=//'` ;; --enable-tls) enable_tls=yes;; --enable-tls=*) enable_tls=`echo "$1" | sed -e 's/[-a-z]*=//'` ;; --disable-tls) enable_tls=no;; *) echo "*** Unrecognized option $1." >&2; error=true;; esac shift done # Convert relative paths to absolute. # Variables that can be set interactively should not be listed here, # see get_install. for i in with_readline with_readline_lib with_readline_include \ with_gmp with_gmp_lib with_gmp_include \ with_ncurses_lib with_qt with_fltk ; do eval "dflt=\"\$$i\"" case $dflt in ''|yes|/*) ;; *) eval "$i='$TOP/$dflt'";; esac done # The behaviour of $prefix/lib --> '//lib' is implementation-dependent case "$prefix" in /) prefix=;; esac case "$share_prefix" in /) prefix=;; esac case "$error" in true) cat >&2 < ] [ --prefix=

] 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 win32) --time= timing function to use (getrusage 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) --enable-tls (*experimental*) enable thread-local stack 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.] EOT exit 1 ;; verb) cat >&2 < #include void f(void) { mpn_gcdext(NULL,NULL, NULL, NULL, 0, NULL, 0); } main() { if (sizeof(mp_limb_t) == sizeof(long)) printf("%s", gmp_version); else printf("unsupported"); } pari-2.5.5/config/has_opendir.c0000644000175000017500000000011511636712103015005 0ustar billbill#include #include main() { DIR *d = opendir("."); } pari-2.5.5/config/version0000644000175000017500000000213412212611624013756 0ustar billbill# Major version number VersionMajor='2' # minor version number VersionMinor='5' # Patch level patch='5' # Version code version_code=`expr $VersionMajor \\* 65536 + $VersionMinor \\* 256 + $patch` # Status: alpha, beta, released, development stat=development vcsversion= # soname of stable libpari.so is libpari.so.$soname_num patchlevel_verbose= if test -d "$TOP/.svn"; then vcsversion="svn-"`svnversion $TOP` else if test -d "$TOP/.git"; then vcsversion="git-"`git log -1 --pretty=format:%h -- $TOP` else if test -d "$TOP/CVS"; then vcsversion="CHANGES-"`$head 1 "$TOP/CHANGES" | awk '{print $4}'` else if test -r "svnversion"; then vcsversion="svn-"`cat svnversion` fi fi fi fi if test -n "$vcsversion"; then status=released patchlevel_verbose="[ $status ]" else status=released fi version=$VersionMajor.$VersionMinor pari_release="$version.$patch" if test `expr $VersionMinor % 2` = 1; then pari_release_verbose="$pari_release (STABLE)" soname_num=`expr '(' $VersionMinor '+' 1 ')' / 2` else pari_release_verbose="$pari_release (DEVELOPMENT VERSION)" soname_num=$patch fi pari-2.5.5/config/has_exp2.c0000644000175000017500000000011611636712103014224 0ustar billbill#include double (*f)(double) = exp2; int main(){ return f != exp2; } pari-2.5.5/config/get_libc0000644000175000017500000000212512147140046014043 0ustar billbill# Looking in libc for some functions. exe=$osname-$arch-tmp$$ _has_list= echo Looking in C lib for some symbols... extra_flags=-lm list=exp2; . ./look list=log2; . ./look extra_flags= list=strftime; . ./look if test -n "$timing_fun"; then list=$timing_fun else case "$osname" in *cygwin*) list='times ftime';; # getrusage based timer always returns 0 *) list='getrusage times ftime';; esac; fi; . ./look list=sigaction; . ./look list=TIOCGWINSZ; . ./look list=getrlimit; . ./look list='stat opendir'; . ./look list=vsnprintf; . ./look list=waitpid; . ./look list=setsid; . ./look list=getenv; . ./look list=isatty; . ./look list=alarm; . ./look # For install(). Do we need libdl.so? # on irix and osf1 -ldl not needed extra_flags= DL_LIBS= list=dlopen; . ./look if test "$has_dlopen" = no; then echo "Try again, with -ldl this time..." extra_flags=-ldl; . ./look if test "$has_dlopen" = yes; then DL_LIBS=-ldl fi fi if test "$has_dlopen" = no; then case "$osname" in os2|darwin) echo "Will use builtin dlopen() support for $osname..." has_dlopen=builtin esac fi pari-2.5.5/config/genkernel0000755000175000017500000000053311636712103014252 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.5.5/config/genfunclist0000755000175000017500000000051111636712103014615 0ustar billbill#! /bin/sh cd "$1" FL=../funclist TMPFL=$FL.tmp$$ find ../functions -name CVS -prune -o -name '.*' -prune -o -name '*~' -prune -o -type f -print | env LANG= LC_COLLATE= LC_ALL= sort | xargs cksum > $TMPFL if cmp $FL $TMPFL >/dev/null 2>&1; then rm -f $TMPFL else echo "File $FL updated." mv $TMPFL $FL fi pari-2.5.5/config/locatesymbol0000755000175000017500000000026212147140046014773 0ustar billbilltry=`(nm $lib | grep $sym)2>/dev/null` if test -z "$try"; then # stripped dynamic library ??? case "$lib" in *.so*) try=`(strings $lib | grep $sym)2>/dev/null`;; esac fi pari-2.5.5/config/has_strftime.c0000644000175000017500000000007611636712103015210 0ustar billbill#include main(){ struct tm *x; strftime("",1,"",x);} pari-2.5.5/config/has_readline.c0000644000175000017500000000010312147140046015124 0ustar billbill#include main() { char *s = readline("?"); } pari-2.5.5/config/TOP_Make.SH0000644000175000017500000000540112147140046014203 0ustar billbillfile=Makefile echo "Extracting $file" rm -f $file dbgobjdir=`echo "$objdir" | sed -e 's/\.[dbgprf]*$//'` dbgobjdir=$dbgobjdir.dbg 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 "Possible targets are:" @echo " all Compilation + Documentation" @echo " gp Compilation" @echo " bench Compilation + quick test" @echo " dobench Test only" @echo " doc Documentation" @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 " distrib,alpha,beta,release Create a new distribution" @echo " snapshot Create a snapshot" @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 $top_test_extra $top_dotest_extra install cleanall cleanobj cleantest install-bin install-doc install-docpdf install-data install-lib-sta install-bin-sta dobench dyntest-all statest-all tune:: @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 doc docps docpdf gpman cleandoc:: cd doc && \$(MAKE) \$@ clean:: cleandoc cleanall 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: cd src; sh ../config/make_emacs_tags ctags: config/make_vi_tags "$TOP/src" checkspaces: config/checkspaces EOT pari-2.5.5/config/get_libpth0000644000175000017500000000252412201162715014415 0ustar billbillcase "$sizeof_long" in 4) addlib64="/usr/local/lib32 /lib32 /usr/lib32";; 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/lib/$multiarch\ /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.5.5/config/has_dlopen.c0000644000175000017500000000010611636712103014626 0ustar billbill#include #include main() {dlopen("a",RTLD_LAZY);} pari-2.5.5/config/ansi.c0000644000175000017500000000005511636712103013447 0ustar billbillint main(int argc, char **argv){ return 0; } pari-2.5.5/config/get_ld0000644000175000017500000000337411636712103013541 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.5.5/config/locate0000755000175000017500000000032211636712103013543 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.5.5/config/make_emacs_tags0000755000175000017500000000513612147140046015406 0ustar billbill#!/bin/sh # Generate a tags file which contains PARI functions, and allows going # to help-message for a PARI functions and to a PARI function of C function # by repeated C-u M-. # If you are reading this, you may enjoy imenu-go.el from # ftp://ftp.math.ohio-state.edu/pub/users/ilya/emacs/ if test -n "$ETAGS"; then etags=$ETAGS else etags=etags fi # Skip language/init.c, gp/gp_init.c and language/helpmessages.c: errors='language/errmsg.c' messages='language/init.h' gp_init='gp/gp_init.h' init_c='language/init.h' excluded=`perl -e 'print join "\n", grep { $_ ne "'$init_c'" and $_ ne "'$errors'" and $_ ne "'$messages'" and $_ ne "'$gp_init'" } <*/*.[chs]>, <*/*/*.[chs]>'` # Start with errmessages (otherwise enums will come first): # /* suppler2 */ errre='\/\*[ \t]*\([a-zA-Z_0-9]+\)[ \t]*\*\/' $etags -r "/$errre/\\1/" $errors # All files which do not require a special processing $etags -a $excluded # Process declarations like # {"polredord",1,(void*)ordred,6,"Gp"}, # => an entry for polredord, and an entry for ordred as well # (so that one may find which PARI function is implemented by the C one) re='[ \t]*{[ \t]*"\([a-zA-Z_0-9]+\)"[ \t]*,[ \t]*[0-9]+[ \t]*,[ \t]*([ \t]*void[ \t]*\*[ \t]*)[ \t]*\([a-zA-Z0-9+]+\)[ \t]*,' $etags -a -l c -o TAGS.tmp -r "/$re/\\1/" -r "/$re/\\2/" $init_c # Process helpmessages too: # "printtex(a): outputs a in TeX format", helpre='[ \t]*"\([a-zA-Z_0-9]+\)[=(]' $etags -a -l c -o TAGS.tmp -r "/$re/\\1/" -r "/$re/\\2/" \ -r "/$helpre/\\1/" $gp_init $etags -a -l c -o TAGS.tmp -r "/$helpre/\\1/" $messages # This would produces a wrong entry size - though AFAIK, nobody uses it # uniq TAGS.tm >> TAGS perl -w014pe 'if (s/^(.*\n)\1+/$1/mg) { # Remove duplicate lines $chars = chomp; s/^((\n.+,)\d+)/ $2 . (length($_) - length($1) - 1) /e; $_ .= ("\f" x $chars); }' TAGS.tmp > TAGS.tm2 # Since we generate *specific* definitions for the functions in the table, # they will be prefered by Emacs over non-specific ones for the code, so we # convert non-specific definitions into specific ones (with \x1): perl -w014pe 'if (s/^( [^\n\x7F\x01]*\b # 1: TAG group (\w+) # 2: word [^\w\x7F\x01\n]* # Most anything \x7F # End of description ) (\d+,\d+\n) # 3: TAGS Trail /$1$2\x01$3/mgx) { # Add specific marking $chars = chomp; s/^((\n.+,)\d+)/ $2 . (length($_) - length($1) - 1) /e; $_ .= ("\f" x $chars); }' TAGS > TAGS.tm1 && mv TAGS.tm1 TAGS cat TAGS.tm2 >> TAGS rm TAGS.tm* pari-2.5.5/config/get_archos0000644000175000017500000000206311636712103014413 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.5.5/config/has_sigaction.c0000644000175000017500000000031011636712103015322 0ustar billbill#include 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.5.5/config/has_times.c0000644000175000017500000000027411636712103014474 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.5.5/config/paricfg.h.SH0000644000175000017500000001134212147140046014446 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_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 fi if test -n "$rl_genericbind"; then echo '#define HAS_RL_GENERIC_BIND' >> $file fi if test -n "$rl_refresh_line_oldproto"; then echo '#define OLD_RL_REFRESH_LINE' >> $file fi if test -n "$rl_save_prompt"; then echo '#define HAS_RL_SAVE_PROMPT' >> $file else if test -n "$_rl_save_prompt"; then echo '#define HAS_UNDERSCORE_RL_SAVE_PROMPT' >> $file fi fi if test -n "$rl_message"; then echo '#define HAS_RL_MESSAGE' >> $file fi if test -n "$rl_completion_matches"; then echo '#define HAS_RL_COMPLETION_MATCHES' >> $file fi if test -n "$rl_completion_func_t"; then echo '#define HAS_RL_COMPLETION_FUNC_T' >> $file fi if test -n "$rl_history"; then echo '#define HAS_HISTORY_H' >> $file fi if test -n "$rl_attempted_completion_over"; then echo '#define HAS_RL_ATTEMPTED_COMPLETION_OVER' >> $file fi if test -n "$rl_completion_query_items"; then echo '#define HAS_RL_COMPLETION_QUERY_ITEMS' >> $file fi if test -n "$rl_bind_key_in_map"; then echo '#define HAS_RL_BIND_KEY_IN_MAP' >> $file fi if test -n "$rl_library_version"; then echo '#define HAS_RL_LIBRARY_VERSION' >> $file fi if test -n "$rl_fake_library_version"; then echo '#define FAKE_RL_LIBRARY_VERSION' >> $file fi echo >> $file fi case "$CPPF_defined" in yes) echo '#define CPPFunction_defined' >> $file;; esac case "$sizeof_long" in 8) echo '#define LONG_IS_64BIT' >> $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_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 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.5.5/config/get_perl0000644000175000017500000000051511636712103014076 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.5.5/config/get_cc0000644000175000017500000001343512147140046013525 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 EOT echo $n ..."Which optimization do you prefer ? $c" dflt=$optimization; rep='full debugging profiling'; . ./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 Looking for the compilers ... # Native Compilers cc=`./locate cc '' $pathspace` case "$osname" in hpux) if test "$cc" = /usr/ccs/bin/cc -a -f /opt/ansic/bin/cc; then cc=/opt/ansic/bin/cc; fi ;; # This is a better compiler esac case "$cc" in ?:/*|/*) echo ..."cc is $cc";; *) echo ..."I could not find cc.";; esac # GNU Compilers gcc=`./locate gcc '' $pathspace` if test -z "$gcc"; then exe=$osname-$arch-gnu$$ $cc $extraflag -o $exe gnu.c if $RUNTEST $exe; then gcc=$cc; fi; rm -f $exe fi case "$gcc" in ?:/*|/*) echo ..."gcc is $gcc";; *) echo ..."I could not find gcc."; gcc=;; esac if test -n "$gcc"; then # avoid internationalization trouble by setting LANG=C __gnuc__=`env LANG=C LC_ALL=C LC_MESSAGES=C $gcc -v 2>&1 | sed -n 's/.*version //p'` if test -z "$__gnuc__"; then __gnuc__=unknown; fi echo GNU compiler version $__gnuc__ fi case "$osname" in aix) __gnuc__=;; # Native compilers are faster hpux) __gnuc__=;; # versions older than 2.7 cannot build PIC code # gp built with recent versions has bugs concentrix) case "$__gnuc__" in 2.[78].*);; *) __gnuc__=;; esac;; esac # Choosing the compiler if test -n "$__gnuc__"; 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++, it is a good idea to include the -fpermissive flag). If you choose not to use gcc, the C++ version of Pari will be a little faster because of general inlining, but can be used in library mode only with C++ programs. 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 exe=$osname-$arch-ansi$$ $CC $CFLAGS $extraflag -o $exe ansi.c 2>/dev/null && $RUNTEST $exe if test $? != 0; then cat << EOT ### ### C compiler does not work. PARI/GP requires an ANSI C compiler! Aborting. ### ### Compiler was: $CC $CFLAGS $extraflag EOT exit 1; fi rm -f $exe $exe$exe_suff if test "$CC" != "$gcc"; then __gnuc__=; fi if test -z "$__gnuc__"; then exe=$osname-$arch-gnu$$ $CC $extraflag -o $exe gnu.c if $RUNTEST $exe; then # avoid internationalization trouble by setting LANG=C __gnuc__=`env LANG=C LC_ALL=C LC_MESSAGES=C $CC -v 2>&1 | sed -n 's/.*version //p'` echo GNU compiler version $__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 case "$asmarch" in alpha) case "$__gnuc__" in 2.95.[3-9]*|[3-9].*) ;; *) ASMINLINE=;; # doesn't work with 2.95.2. esac ;; esac OPTFLAGS="$OPTFLAGS $warn" case "$__gnuc__" in 2.95.[3-9]*|[3-9].*) OPTFLAGS="$OPTFLAGS -fno-strict-aliasing";; esac 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 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" 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";; esac CFLAGS="$cflags $CFLAGS $CPPFLAGS" if test "$fastread" != yes; then echo $n ..."With which flags ? $c" dflt=$CFLAGS; rep=; . ./myread CFLAGS=$ans fi multiarch=`$CC $CFLAGS -print-multiarch 2>/dev/null` pari-2.5.5/config/setversion0000755000175000017500000000067312147140046014505 0ustar billbill#!/bin/sh # to be run from the Oxxx directory 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.5.5/config/make_vi_tags0000755000175000017500000000330312147140046014726 0ustar billbilleval 'exec perl "$0" "$1"' if $running_under_some_shell; use File::Find 'find'; # Build a (sorted) VI(M) tags file including GP functions # $src=$ARGV[0] || "$ENV{HOME}/PARI/src"; $tmptags="$src/tags.tmp"; # Case sensitive? $tags = $^O eq 'os2' ? "$src/ctags" : "$src/tags"; @tags = ""; $old = ""; @files = (); find \&filter_c, $src; # Note that shell uses a different logic than perl, # so the following `&&' correspond to `||' in shell. # Assume ctags outputs sorted tags (e.g Exuberant Ctags) 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"); getnames("$src/gp/gp_init.h"); getnames("$src/language/init.h"); geterrs("$src/language/errmsg.c"); open(T,"$tmptags"); for (sort(@gp)) { ($a, $b) = split(/#/); 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,$_); } close(T); open(OUT,">$tags"); print OUT sort(@tags); unlink $tmptags; sub getnames { open(A,$_[0]); while () { if (/^entree functions_/../^$/) { push(@gp,"$2#$1") if (/[^"]*"([^"]*)".*\(void\*\) *([^,]*)/); } } close(A); } sub geterrs { my $f = $_[0]; open(A,$f); while () { if (m,/(\*\s*\w+\s*\*)/,) { $e = $pat = $1; $e =~ s/\W*(\w+)\W*/$1/; push(@tags, "$e\t$f\t/$pat\n"); } } close(A); } sub filter_c { return unless /\.[chy]\Z/ && -f; return if (/(tune|kerntest|parse)\.c/); push @files, "$File::Find::name"; } pari-2.5.5/config/Makefile.SH0000644000175000017500000005013512147140046014325 0ustar billbillfile=$objdir/Makefile echo Extracting $file rm -f $file # Path to directories cfg=../$config_dir data=../$data_dir doc=../$doc_dir desc=../$desc_dir ex=../$examples_dir misc=../$misc_dir src=../$src_dir knone=$src/kernel/none kern0=$src/kernel/$kernlvl0 kern1=$src/kernel/$kernlvl1 # # File lists # kernel="mp mpinl" gp=`ls $src_dir/gp/*.c | sed 's,.*/\(.*\)\.c,\1,'` language=`ls $src_dir/language/*.c | sed 's,.*/\(.*\)\.c,\1,'` basemath=`ls $src_dir/basemath/*.c | sed 's,.*/\(.*\)\.c,\1,'` modules=`ls $src_dir/modules/*.c | sed 's,.*/\(.*\)\.c,\1,'` systems= if test -d "$src_dir/systems/$osname"; then systems=`ls $src_dir/systems/$osname/*.c | sed 's,.*/\(.*\)\.c,\1,'` fi # remove paridecl: no general recompilation when only changing a prototype hlist=`ls $src_dir/headers/*.h | grep -v paridecl | grep -v paripriv |\ sed 's,.*/\(.*\)\.h,\1,'` # for installation put paridecl back. Remove \n otherwise make will choke. headerlist="paridecl paripriv `echo $hlist| tr '\n' ' '`" #Add src/language/parse.c if it is not yet generated case $language in *parse*);; *) language="$language parse";; esac # special systems (OS/2 for now) shortlib_prefix=lib lib_prefix=lib dllib_prefix=lib case "$osname" in os2) shortlib_prefix= # 8.3 filenames dllib_prefix= # != lib_prefix to allow gp-dyn link with DLL export_lib_create=emximp; export_lib='$(DLLIBPARI)$(_A)' export_file=pari.def; export_create="emxexp -u" # Actually, the build will fail until the switch to -Zomf dlld_ignore=- ;; mingw) export_file='$(LIBPARI).def';; darwin) ld_install_name="-Wl,-install_name -Wl,\"$libdir\"/\$(LIBPARI_DYN)";; esac PLOTCFLAGS= PLOTLIBS= postconfig="@: " case "$which_graphic_lib" in none) graph=plotnull;; Qt) PLOTCFLAGS='-D__FANCY_WIN__ -I$(QTDIR)/include' PLOTLIBS="-L\$(QTDIR)/lib $QTLIB" graph=plotQt;; Qt4) PLOTCFLAGS='-D__FANCY_WIN__ -I$(QTDIR)/include' PLOTLIBS="-L\$(QTDIR)/lib $QTLIB" graph=plotQt4;; fltk) PLOTCFLAGS="-I\$(FLTKDIR)/include $X11_INC" PLOTLIBS="-L\$(FLTKDIR)/lib -lfltk $FLTK_LIBS" postconfig='-fltk-config --post ' graph=plotfltk;; win32) PLOTLIBS="-lgdi32" graph=plotWin32;; esac graph="plotport $graph" plotrunpath= case "$which_graphic_lib" in *X11*) PLOTCFLAGS="$PLOTCFLAGS $X11_INC" PLOTLIBS="$PLOTLIBS $X11_LIBS" plotrunpath=$X11 graph="plotX $graph" ;; esac KERNOBJS= for f in $kernel; do KERNOBJS="$KERNOBJS $f\$(_O)" done OBJS=$KERNOBJS for f in $basemath $language $modules $systems; do OBJS="$OBJS $f\$(_O)" done OBJSGP= for f in $gp $graph; do OBJSGP="$OBJSGP $f\$(_O)" done HEADERS=mpinl.h for f in $hlist; do HEADERS="$HEADERS $src/headers/$f.h"; done # runpath tmp=$runpath for d in "$plotrunpath" "$gmp" "$readline" "/usr/lib"; do if test -n "$d"; then case "$tmp" in $d|*$dir_sep$d|*$dir_sep$d$dir_sep*);; *) tmp="$tmp$dir_sep$d";; esac fi done RUNPTH_FINAL= RUNPTH= if test -n "$runpathprefix"; then RUNPTH_FINAL=`$config_dir/ldflags "$LDneedsWl" $runpathprefix"$tmp"` RUNPTH=`$config_dir/ldflags "$LDneedsWl" $runpathprefix\\\$\(TOPDIR\)/$objdir$dir_sep"$tmp"` fi if test -z "$DLLD"; then exec="gp-sta"; static=y else exec="gp-sta gp-dyn" fi case "$sizeof_long" in 4) numbits=32;; 8) numbits=64;; esac dotest="env \"RUNTEST=\$(RUNTEST)\" \"LD_LIBRARY_PATH=.$dir_sep\$\$LD_LIBRARY_PATH\" \$(SHELL) $src/test/dotest $numbits" case "$static" in n) dft=dyn; libdft=lib-dyn;; y) dft=sta; libdft= ;; esac CPPFLAGS="-I. -I$src/headers" if test "$has_dlopen" = builtin; then CPPFLAGS="$CPPFLAGS -I$src/systems/$osname" fi case "$ln_s" in *cp*) ln_objdir=".";; *) ln_objdir="$objdir" esac cat > $file << EOT # Makefile for Pari/GP -- $pretty # # This file was created by Configure. Any change made to it will be # lost when Configure is run. # TOPDIR="$TOP" SHELL = $make_sh PERL = $perl BISON = bison AR = ar SIZEOF_LONG= $sizeof_long CC_FLAVOR = CC = $CC \$(CC_FLAVOR) CPPFLAGS = $CPPFLAGS CFLAGS = $CFLAGS DLCFLAGS = $DLCFLAGS KERNELCFLAGS = $KERNELCFLAGS LD_FLAVOR = \$(CC_FLAVOR) LD = $LD \$(LD_FLAVOR) LDFLAGS = $LDFLAGS DLLD_FLAVOR = \$(LD_FLAVOR) DLLD = $DLLD \$(DLLD_FLAVOR) DLLDFLAGS = $DLLDFLAGS EXTRADLLDFLAGS = $EXTRADLLDFLAGS RUNTEST = $RUNTEST # HIGHLY EXPERIMENTAL (only tested with gmp-4.0 on ix86 and Ultra). # If you've configured and compiled GMP and would like to tune PARI using # the nice cycle counting functions in GMP, uncomment the 4 lines below # (correct the first one to the path to your gmp source tree). # #GMP = /some/directory/gmp-4.0/tune #GMPFLAGS= -DGMP_TIMER #GMPO1 = \$(GMP)/time.o \$(GMP)/freq.o #GMPOBJS=\$(GMPO1) \$(GMPO2) # #You may need to add a few object files to GMPOBJS. On UltraSparc, uncomment #the following line #GMPO2 = \$(GMP)/sparcv9.o _O = .o _A = .a LIB_PREFIX = $lib_prefix DLLIB_PREFIX = $dllib_prefix LIBPARI_BASE = $libpari_base LIBPARI = \$(LIB_PREFIX)pari DLLIBPARI = \$(DLLIB_PREFIX)pari LIBPARI_STA = \$(LIBPARI)\$(_A) LIBPARI_SO = \$(DLLIBPARI).$DLSUFFIX SOLIBPARI = \$(DLLIB_PREFIX)\$(LIBPARI_BASE).$DLSUFFIX LIBPARI_DYN = \$(SOLIBPARI)$sodest LIBPARI_SONAME= \$(SOLIBPARI)$soname DL_DFLT_NAME = $DL_DFLT_NAME LD_INSTALL_NAME = $ld_install_name EXPORT_FILE = $export_file EXPORT_CREATE = $export_create EXPORT_LIB = $export_lib EXPORT_LIB_CREATE = $export_lib_create DLLD_IGNORE = $dlld_ignore DLLTOOL = $DLLTOOL RUNPTH = $RUNPTH RUNPTH_FINAL = $RUNPTH_FINAL LDDYN = $LDDYN LIBS = $LIBS GMPLIBS = $GMPLIBS DL_LIBS = $DL_LIBS STA_LIBS = \$(GMPLIBS) \$(LIBS) RM = rm -f MV = mv -f LN = $ln_s CP_F = cp -f STRIP = strip STRIPFLAGS = # Change these installation directories to suit your needs. # DESTDIR is used to install to a false hierachy (to build a Debian package) INCLUDEDIR= "\$(DESTDIR)$includedir" LIBDIR = "\$(DESTDIR)$libdir" BINDIR = "\$(DESTDIR)$bindir" MANDIR = "\$(DESTDIR)$mandir" DATADIR = "\$(DESTDIR)$datadir" SYSDATADIR= "\$(DESTDIR)$sysdatadir" EXDIR = \$(DATADIR)/examples MISCDIR = \$(DATADIR)/misc DOCDIR = \$(DATADIR)/doc INSTALL = $cfg/install INSTALL_PROGRAM = \$(INSTALL) INSTALL_DATA = \$(INSTALL) -m 644 # Readline RLINCLUDE = $RLINCLUDE RLLIBS = $RLLIBS # GMP GMPINCLUDE = $GMPINCLUDE # Graphic library. QTDIR = "$QTDIR" MOC = \$(QTDIR)/bin/moc PLOTCFLAGS = $PLOTCFLAGS PLOTLIBS = $PLOTLIBS CPLUSPLUS = g++ FLTKDIR = "$FLTKDIR" TOPLDDYN = "$TOP/$objdir" # Description system DESC = pari.desc DESC_HELP_GEN = $desc/gen_proto $desc/PARI/822.pm TMPSUF = $osname-$arch.tmp DOTEST=$dotest OBJS = $OBJS OBJSGP = $OBJSGP .PHONY: gp dft clean gp: gp-$dft ../gp$suffix$exe_suff $libdft ../gp$suffix$exe_suff: gp-$dft -\$(RM) \$@ -\$(LN) $ln_objdir/gp-$dft \$@ all: $exec lib-sta lib-sta: \$(LIBPARI_STA) lib-dyn: \$(LIBPARI_DYN) \$(LIBPARI_STA): $add_funclist \$(OBJS) -\$(RM) \$@ \$(AR) r \$@ \$(OBJS) -$ranlib \$@ kerntest\$(_O): $src/test/kerntest.c \$(CC) -c -I$src/language \$(CPPFLAGS) \$(CFLAGS) -o \$@ $src/test/kerntest.c dummy\$(_O): $src/test/dummy.c \$(CC) -c \$(CPPFLAGS) \$(CFLAGS) -o \$@ $src/test/dummy.c kerntest: $KERNOBJS dummy\$(_O) kerntest\$(_O) \$(CC) \$(CPPFLAGS) \$(CFLAGS) -o \$@ $KERNOBJS dummy\$(_O) kerntest\$(_O) \$(STA_LIBS) mpinl\$(_O): .headers parilvl0.h parilvl1.h $knone/mpinl.c \$(CC) -c \$(CPPFLAGS) \$(CFLAGS) \$(DLCFLAGS) -o mpinl\$(_O) $knone/mpinl.c test-kernel:: kerntest @./kerntest > gp.out;\ diff -c gp.out $src/test/$numbits/kernel > kern.dif;\ if test -s kern.dif; then echo "KERNEL BUG"; else echo OK; fi tune.o: $src/test/tune.c \$(CC) \$(GMPFLAGS) \$(CPPFLAGS) \$(CFLAGS) -o \$@ \$< -c tune: mpinl.h tune-sta -\$(RM) tune ../tune -\$(LN) tune-sta tune -\$(LN) $ln_objdir/tune ../tune tune-dyn: tune.o \$(LIBPARI_DYN) \$(LD) -L. \$(LDFLAGS) \$(RUNPTH) -o \$@ \$< \$(GMPOBJS) \$(LDDYN) \$(STA_LIBS) tune-sta: tune.o \$(LIBPARI_STA) \$(LD) \$(LDFLAGS) \$(RUNPTH) -o \$@ \$< \$(GMPOBJS) ./\$(LIBPARI_STA) \$(STA_LIBS) gp-sta: $add_funclist \$(OBJS) \$(OBJSGP) \$(RM) \$@ \$(LD) -o \$@ \$(LDFLAGS) \$(OBJS) \$(OBJSGP) \$(RUNPTH) \$(RLLIBS) \$(PLOTLIBS) \$(DL_LIBS) \$(STA_LIBS) $postconfig gp-sta cleantest: \$(RM) *.dif gp.out pari.ps cleanobj: -\$(RM) *\$(_O) mp.c *.s mpinl.h parilvl0.h parilvl1.h libpari* $exec kerntest cleandesc: -\$(RM) $desc/\$(DESC) *\$(TMPSUF) cleantune: -\$(RM) tune tune-sta tune.o cleanall: cleanobj cleantune cleantest cleandesc clean: cleanall # sleep 3 to avoid problems with NFS and slightly out of synch # fileserver/host. We are recompiling everything anyway. .headers: $HEADERS @sleep 3; touch \$@ install: install-lib-$dft install-include install-bin install-man install-misc install-doc install-examples install-cfg install-data install-include: -mkdir -p \$(INCLUDEDIR)/pari -for i in paricfg.h mpinl.h; do \\ \$(INSTALL_DATA) \$\$i \$(INCLUDEDIR)/pari; done -for i in $headerlist; do \\ \$(INSTALL_DATA) $src/headers/\$\$i.h \$(INCLUDEDIR)/pari; done -\$(RM) \$(INCLUDEDIR)/pari/genpari.h -\$(LN) pari.h \$(INCLUDEDIR)/pari/genpari.h install-bin: install-bin-$dft install-bin-dyn: gp-dyn install-lib-dyn -mkdir -p \$(BINDIR) -\$(RM) \$(BINDIR)/gp-$version$exe_suff \$(BINDIR)/gp$exe_suff \$(LD) -o \$(BINDIR)/gp-$version$exe_suff -L\$(LIBDIR) \$(LDFLAGS) \$(OBJSGP) \$(RUNPTH_FINAL) \$(LDDYN) \$(RLLIBS) \$(PLOTLIBS) \$(LIBS) \$(DL_LIBS) -\$(STRIP) \$(STRIPFLAGS) \$(BINDIR)/gp-$version$exe_suff $postconfig \$(BINDIR)/gp-$version$exe_suff -\$(LN) gp-$version$exe_suff \$(BINDIR)/gp$exe_suff install-bin-sta: gp-sta -mkdir -p \$(BINDIR) -\$(RM) \$(BINDIR)/gp-$version$exe_suff \$(BINDIR)/gp$exe_suff \$(INSTALL_PROGRAM) gp-sta \$(BINDIR)/gp-$version$exe_suff -\$(LN) gp-$version$exe_suff \$(BINDIR)/gp$exe_suff # Can't strip it if we want install() to work on OSF. # -\$(STRIP) \$(STRIPFLAGS) \$(BINDIR)/gp-$version $postconfig \$(BINDIR)/gp-$version$exe_suff install-man:: -mkdir -p \$(MANDIR) -\$(RM) \$(MANDIR)/pari.1 \$(MANDIR)/gp.1 \$(MANDIR)/gp-$version.1 \$(INSTALL_DATA) $doc/gphelp.1 \$(MANDIR) \$(INSTALL_DATA) $doc/gp.1 \$(MANDIR)/gp-$version.1 -\$(LN) gp.1 \$(MANDIR)/pari.1 -\$(LN) gp-$version.1 \$(MANDIR)/gp.1 install-misc: -mkdir -p \$(MISCDIR) \$(BINDIR) \$(INSTALL_PROGRAM) $misc/tex2mail \$(BINDIR) \$(INSTALL_DATA) $doc/tex2mail.1 \$(MANDIR) \$(INSTALL_DATA) $misc/README \$(MISCDIR) \$(INSTALL_DATA) $misc/color.dft \$(MISCDIR) \$(INSTALL_DATA) $misc/gpalias \$(MISCDIR) \$(INSTALL_PROGRAM) $misc/gpflog \$(MISCDIR) \$(INSTALL_DATA) $misc/gprc.dft \$(MISCDIR) \$(INSTALL_DATA) $misc/pari.xpm \$(MISCDIR) \$(INSTALL_PROGRAM) $misc/xgp \$(MISCDIR) install-cfg:: -mkdir -p \$(SYSDATADIR) -\$(INSTALL_DATA) pari.cfg \$(SYSDATADIR) -if test -n "$add_funclist"; then\ mkdir -p \$(DATADIR)/PARI;\ \$(INSTALL_DATA) $desc/PARI/822.pm \$(DATADIR)/PARI;\ \$(INSTALL_DATA) $desc/\$(DESC) \$(DATADIR); fi install-doc:: -mkdir -p \$(BINDIR) \$(DOCDIR) -cd $doc; \$(MAKE) all -\$(INSTALL_PROGRAM) $doc/gphelp \$(BINDIR) -\$(INSTALL_DATA) $doc/Makefile \$(DOCDIR) -\$(INSTALL_DATA) $doc/translations \$(DOCDIR) -\$(INSTALL_DATA) $doc/appa.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/appb.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/appd.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/parimacro.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/pdfmacs.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/refcard.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/tutorial.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/users.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/usersch1.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/usersch2.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/usersch3.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/usersch4.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/usersch5.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/paricfg.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/libpari.dvi \$(DOCDIR) -\$(INSTALL_DATA) $doc/users.dvi \$(DOCDIR) -\$(INSTALL_DATA) $doc/tutorial.dvi \$(DOCDIR) -\$(INSTALL_DATA) $doc/refcard.dvi \$(DOCDIR) -\$(INSTALL_DATA) $doc/refcard.ps \$(DOCDIR) install-docpdf:: -mkdir -p \$(BINDIR) \$(DOCDIR) -cd $doc; \$(MAKE) docpdf -\$(INSTALL_DATA) $doc/libpari.pdf \$(DOCDIR) -\$(INSTALL_DATA) $doc/users.pdf \$(DOCDIR) -\$(INSTALL_DATA) $doc/tutorial.pdf \$(DOCDIR) -\$(INSTALL_DATA) $doc/refcard.pdf \$(DOCDIR) install-examples: -mkdir -p \$(EXDIR) -\$(INSTALL_DATA) $ex/EXPLAIN \$(EXDIR) -\$(INSTALL_DATA) $ex/Inputrc \$(EXDIR) -\$(INSTALL_DATA) $ex/Makefile \$(EXDIR) -\$(INSTALL_DATA) $ex/bench.gp \$(EXDIR) -\$(INSTALL_DATA) $ex/cl.gp \$(EXDIR) -\$(INSTALL_DATA) $ex/classno.gp \$(EXDIR) -\$(INSTALL_DATA) $ex/contfrac.gp \$(EXDIR) -\$(INSTALL_DATA) $ex/lucas.gp \$(EXDIR) -\$(INSTALL_DATA) $ex/extgcd.c \$(EXDIR) -\$(INSTALL_DATA) $ex/rho.gp \$(EXDIR) -\$(INSTALL_DATA) $ex/squfof.gp \$(EXDIR) -\$(INSTALL_DATA) $ex/taylor.gp \$(EXDIR) install-data: -if test -d $data; then cd $data; \ for d in \`ls\`; do \ mkdir -p \$(DATADIR)/\$\$d && \ for f in \`ls \$\$d\`; do \ \$(INSTALL_DATA) \$\$d/\$\$f \$(DATADIR)/\$\$d; \ done >/dev/null;\ done; \ fi install-lib-sta: \$(LIBPARI_STA) -mkdir -p \$(LIBDIR) -\$(RM) \$(LIBDIR)/\$(LIBPARI_STA) \$(INSTALL_DATA) \$(LIBPARI_STA) \$(LIBDIR)/\$(LIBPARI_STA) install-lib-dyn-base: -mkdir -p \$(LIBDIR) -\$(RM) \$(LIBDIR)/\$(LIBPARI_DYN) \$(LIBDIR)/\$(LIBPARI_SONAME) \$(LIBDIR)/\$(LIBPARI_SO) \$(DLLD_IGNORE)\$(DLLD) -o \$(LIBDIR)/\$(LIBPARI_DYN) \$(DLLDFLAGS) \$(OBJS) \$(EXTRADLLDFLAGS) \$(GMPLIBS) \$(EXPORT_FILE) \$(LD_INSTALL_NAME) install-lib-dyn-link: install-lib-dyn-base -if test "\$(LIBPARI_SONAME)" != "\$(LIBPARI_SO)"; then \ \$(LN) \$(LIBPARI_DYN) \$(LIBDIR)/\$(LIBPARI_SONAME);\ \$(LN) \$(LIBPARI_DYN) \$(LIBDIR)/\$(LIBPARI_SO); fi install-lib-dyn: \$(LIBPARI_DYN) install-lib-dyn-link mpinl.h: parilvl0.h parilvl1.h cat parilvl0.h parilvl1.h > mpinl.h bench: $exec @\$(DOTEST) $test_basic dobench:: @\$(DOTEST) $test_basic test-all: $exec @\$(DOTEST) $test_extra dotest-all:: @\$(DOTEST) $test_extra dyntest-all: gp-dyn @env dotestSUF=dyn make test-all statest-all: gp-sta @env dotestSUF=sta make test-all EOT for i in $test_extra $test_extra_out; do cat >> $file << EOT test-$i: $exec @\$(DOTEST) $i dotest-$i:: @\$(DOTEST) $i EOT done if test -z "$DLLD"; then cat >> $file << EOT \$(LIBPARI_DYN):: @echo "Configure could not find a way to build a shared library on this machine" EOT else if test -n "$export_file"; then case "$osname" in os2) cat >> $file << EOT EXPORT_FILE_BASE = $src/systems/os2/pari.def.base VERSION_VERBOSE = $pari_release_verbose \$(EXPORT_FILE): \$(OBJS) \$(EXPORT_FILE_BASE) cat \$(EXPORT_FILE_BASE) | sed 's//\$(DLLIBPARI)/' | sed 's//pari.math.u-bordeaux.fr\//' | sed 's//\$(VERSION_VERBOSE)/' | sed 's//GP\/PARI compiled with \$(CFLAGS)/' > \$@ \$(EXPORT_CREATE) \$(OBJS) >> \$@ \$(DLLIBPARI)\$(_A): \$(EXPORT_FILE) \$(EXPORT_LIB_CREATE) -o \$@ \$(EXPORT_FILE) EOT ;; mingw) cat >> $file << EOT \$(EXPORT_FILE): \$(OBJS) \$(DLLTOOL) --export-all-symbols -k -z \$@.tmp \$(OBJS) echo "LIBRARY \$(LIBPARI)" > \$@ && cat \$@.tmp >> \$@ && rm \$@.tmp EOT ;; esac fi cat >> $file << EOT gp-dyn: $add_funclist \$(OBJSGP) \$(LIBPARI_DYN) \$(EXPORT_LIB) \$(RM) \$@ \$(LD) -o \$@ -L\$(TOPLDDYN) \$(LDFLAGS) \$(OBJSGP) \$(RUNPTH) \$(RLLIBS) \$(LDDYN) \$(PLOTLIBS) \$(LIBS) \$(DL_LIBS) $postconfig gp-dyn \$(LIBPARI_DYN): $add_funclist \$(OBJS) \$(EXPORT_FILE) -\$(RM) \$(LIBPARI_DYN) \$(DLLD_IGNORE)\$(DLLD) -o \$(TOPLDDYN)/\$(LIBPARI_DYN) \$(DLLDFLAGS) \$(OBJS) \$(EXTRADLLDFLAGS) \$(GMPLIBS) \$(EXPORT_FILE) -if test "\$(LIBPARI_DYN)" != "\$(LIBPARI_SO)"; then \ \$(RM) \$(LIBPARI_SO);\ \$(LN) \$(LIBPARI_DYN) \$(LIBPARI_SO); fi -if test "\$(LIBPARI_DYN)" != "\$(LIBPARI_SONAME)"; then \ \$(RM) \$(LIBPARI_SONAME);\ \$(LN) \$(LIBPARI_DYN) \$(LIBPARI_SONAME); fi EOT fi cat >> $file << EOT $src/language/parse.h: $src/language/parse.y \$(BISON) -d $src/language/parse.y -o $src/language/parse.c $src/language/parse.c: $src/language/parse.h @: EOT if test -n "$add_funclist"; then # files generated using external scripts HUGELINE=" $src/funclist:: @-$cfg/genfunclist $desc" suffix='$$$$-$(TMPSUF)' list="funclist whatnow init default gp_default gp_init highlvl" for name in $list; do case $name in funclist) target="$desc/\$(DESC)" depend="$src/funclist $desc/merge_822 $desc/PARI/822.pm" script="merge_822 ../funclist" ;; whatnow) target=$src/gp/whatnow.h depend="$desc/whatnow $src/whatnow" script=whatnow ;; init) target=$src/language/init.h depend="$desc/\$(DESC) \$(DESC_HELP_GEN)" script="gen_proto basic \$(DESC)" ;; default) target=$src/language/default.h depend="$desc/\$(DESC) \$(DESC_HELP_GEN)" script="gen_proto default \$(DESC)" ;; gp_default) target=$src/gp/gp_default.h depend="$desc/\$(DESC) \$(DESC_HELP_GEN)" script="gen_proto gp_default \$(DESC)" ;; gp_init) target=$src/gp/gp_init.h depend="$desc/\$(DESC) \$(DESC_HELP_GEN)" script="gen_proto gp \$(DESC)" ;; highlvl) target=$src/gp/highlvl.h depend="$desc/\$(DESC) \$(DESC_HELP_GEN)" script="gen_proto highlevel \$(DESC)" ;; esac HUGELINE="$HUGELINE $target: $depend f=$name-$suffix; (cd $desc && \$(PERL) $script > \$\$f) && mv $desc/\$\$f \$@" done echo "$HUGELINE" >> $file fi # Level 0 f=$src_dir/kernel/$kernlvl0/MakeLVL0.SH if test -s $f; then . $f else cat >> $file < parilvl0.h EOT fi if test -f $TOP/.svn/entries; then vcfile="../.svn/entries" else if test -f $TOP/.git/index; then vcfile="../.git/index" fi fi if test -n "$vcfile"; then cat >> $file <> $file pari-2.5.5/config/gnu.c0000644000175000017500000000011111636712103013277 0ustar billbill#ifdef __GNUC__ int main(){return 0;} #else int main(){return 1;} #endif pari-2.5.5/config/extract_files0000755000175000017500000000110411636712103015127 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.5.5/config/get_graphic_lib0000644000175000017500000000344712147140046015405 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 -z "$has_waitpid" -o -z "$has_setsid"; then echo "### Missing waitpid() or setsid(), no Hi-Res graphing window" which_graphic_lib=none else if test -n "$with_fltk"; then which_graphic_lib=fltk; fi if test -n "$with_qt"; then which_graphic_lib=Qt; fi if test "$which_graphic_lib" != none; then case $osname in mingw) case $which_graphic_lib in win32|auto) which_graphic_lib=win32;; esac;; *) . ./get_X11 # X11,X11_INC,X11_LIBS. if test -z "$X11"; then case $which_graphic_lib in X11) which_graphic_lib=none;; esac else case $which_graphic_lib in auto) which_graphic_lib=X11;; esac fi;; esac fi if test "$fastread" != yes; then cat << EOT ========================================================================== GP contains high resolution plotting functions. Choose among none X11 fltk Qt win32 EOT echo $n ..."Use which graphic library (\"none\" means no hi-res plot) ? $c" rep="none X11 fltk Qt win32"; dflt=$which_graphic_lib; . ./myread which_graphic_lib=$ans fi fi case $which_graphic_lib in auto|fltk) . ./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 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 fi;; esac case $which_graphic_lib in auto) which_graphic_lib=none;; esac echo "Hi-Res Graphics: $which_graphic_lib" pari-2.5.5/config/myread0000755000175000017500000000075211636712103013564 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.5.5/config/get_pretty0000644000175000017500000000064011636712103014462 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.5.5/config/has_waitpid.c0000644000175000017500000000013611636712103015011 0ustar billbill#include #include #include main(){ waitpid(-1,NULL,0); } pari-2.5.5/config/get_modld0000644000175000017500000000162611636712103014237 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 -flat_namespace -undefined suppress \ \$(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.5.5/config/has_getenv.c0000644000175000017500000000006011636712103014634 0ustar billbill#include main(){ (void)getenv(""); } pari-2.5.5/config/get_tests0000644000175000017500000000161311636712103014276 0ustar billbill# Format: filename_weight (weight = 1000 if omitted) # individual times are printed as is, but accumulated time is weighed # by (weight / 1000) _test_list='test_extra_out test_extra test_basic top_test_extra top_dotest_extra' # _not_ included in 'make test-all' (annoying) test_extra_out="ploth" # included in 'make bench' test_basic="\ objets\ analyz\ number\ polyser\ linear\ elliptic\ sumiter\ graph\ program\ trans\ nfields_200\ " pattern_out=`echo $test_extra_out | sed -e 's/ /|/'` # included in 'make test-all' in addition to regular components of 'make bench' test_extra=`ls "$TOP"/src/test/in | egrep -v "CVS|$pattern_out"` test_extra=`echo $test_extra | sed -e 's/\n/ /g'` top_test_extra="test-`echo $test_extra $test_extra_out | sed -e 's/ \\([^ ]\\)/ test-\\1/g'`" top_dotest_extra="dotest-`echo $test_extra $test_extra_out | sed -e 's/ \\([^ ]\\)/ dotest-\\1/g'`" pari-2.5.5/config/Imakefile0000644000175000017500000000016311636712103014162 0ustar billbillgp-X11: @echo 'Xincroot="${INCROOT}"; usrlibdir="${USRLIBDIR}"; libdir="${LIBDIR}";extralib="${EXTRA_LIBRARIES}"' pari-2.5.5/config/has_getrusage.c0000644000175000017500000000031611636712103015336 0ustar billbill#define _INCLUDE_POSIX_SOURCE #include #include #include #include #include main(){ struct rusage a; printf("%d",getrusage(RUSAGE_SELF,&a));} pari-2.5.5/config/has_log2.c0000644000175000017500000000011611636712103014211 0ustar billbill#include double (*f)(double) = log2; int main(){ return f != log2; } pari-2.5.5/config/get_dlld0000644000175000017500000000751112141040641014047 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="-flat_namespace -undefined suppress -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" in sparc*) 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.5.5/config/display0000755000175000017500000000046511636712103013751 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.5.5/config/rl_version.c0000644000175000017500000000032512147140046014676 0ustar billbill#include #include #ifndef HAS_RL_LIBRARY_VERSION extern char *rl_library_version; /* Might be mismatched header, try anyway! */ #endif main(){ printf("%s", rl_library_version); } pari-2.5.5/config/has_stat.c0000644000175000017500000000034411636712103014324 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.5.5/config/has_isatty.c0000644000175000017500000000005111636712103014661 0ustar billbill#include main(){ isatty(0); } pari-2.5.5/config/has_wait.c0000644000175000017500000000012611636712103014313 0ustar billbill#include #include #include main(){ wait(NULL); } pari-2.5.5/config/get_kernel0000644000175000017500000000706212147140046014417 0ustar billbill# Testing Architectures. Try uname to provide a default, then ask user. # case "$arch" in sparc) asmarch=sparcv8_micro; prettya=Sparc ;; sparcv8_micro) asmarch=$arch; prettya=MicroSparc ;; sparcv8_super) asmarch=$arch; prettya=SuperSparc ;; sparcv9) case "$sizeof_long" in 4) asmarch=sparcv8_micro;; 8) asmarch=none;; esac; prettya=UltraSparc ;; i?86) case "$sizeof_long" in 4) asmarch=ix86;; 8) asmarch=x86_64;; esac; prettya=$arch ;; x86_64) case "$sizeof_long" in 4) asmarch=ix86;; 8) asmarch=x86_64;; esac; prettya='amd64';; ia64) case "$sizeof_long" in 4) asmarch=none;; 8) asmarch=ia64;; esac; prettya=Itanium;; hppa) case "$sizeof_long" in 4) asmarch=hppa; prettya='PA-RISC1.1';; 8) asmarch=hppa64; prettya='PA-RISC2.0';; esac;; alpha) asmarch=$arch; prettya=Alpha ;; ppc|ppc64) case "$sizeof_long" in 4) asmarch=ppc;; 8) asmarch=ppc64;; esac; prettya='PowerPC' ;; arm*) asmarch=none; prettya=$arch ;; mips) asmarch=none; prettya=MIPS ;; m68k) asmarch=m68k; prettya='Motorola 68k';; sh3) asmarch=none; prettya=SH-3 ;; sh5) asmarch=none; prettya=SH-5 ;; vax) asmarch=none; prettya=VAX ;; fx2800) asmarch=none; prettya='Alliant FX/2800' ;; s390) asmarch=none; prettya='S/390' ;; none) asmarch=none; prettya=unknown ;; *) asmarch=none; prettya=$arch echo " Warning ! architecture $arch not tested";; esac # # Modifications for pretty name and asm file # tmp_kern=auto-auto if test -n "$kernel"; then tmp_kern=$kernel else if test "$fastread" != yes; then cat << EOM An optimized Pari kernel is available for these architectures ("none" means that we will use the portable C version of GP/PARI) ("-gmp" means we will use the GMP library (that needs to be installed)) EOM rep='none sparcv8_super sparcv8_micro ix86 alpha hppa m68k ppc ppc64 x86_64 none-gmp sparcv8_super-gmp sparcv8_micro-gmp ix86-gmp alpha-gmp hppa-gmp m68k-gmp ppc-gmp ppc64-gmp x86_64-gmp' . ./display echo $n ..."Which of these apply, if any ? $c" dflt=$asmarch; . ./myread; kernel=$ans # explicit kernel, needed when checking for gmp in Configure tmp_kern=$ans cat << EOM ========================================================================== EOM fi fi if test -z "$without_gmp" ; then lvl1=gmp else lvl1=none fi tmp_kern=`./kernel-name $tmp_kern $asmarch $lvl1` kernlvl0=`echo "$tmp_kern" | sed -e 's/\(.*\)-.*/\1/'` kernlvl1=`echo "$tmp_kern" | sed -e 's/.*-\(.*\)/\1/'` case "$kernlvl0" in none) prettyk0="portable C";; m68k) prettyk0="m68k";; sparcv8_super) prettyk0=SuperSparc;; sparcv8_micro) prettyk0=MicroSparc;; ix86) prettyk0=ix86;; ia64) prettyk0=ia64;; hppa) prettyk0=HPPA;; hppa64) prettyk0=HPPA64;; alpha) prettyk0=Alpha;; ppc) prettyk0=PPC;; ppc64) prettyk0=PPC64;; x86_64) prettyk0="x86-64";; *) prettyk0="$kernlvl0";; esac . get_pretty echo "Building for: $pretty" cat << EOM ========================================================================== EOM pari-2.5.5/config/get_readline0000644000175000017500000001600412212611011014702 0ustar billbillif test "$optimization" = profiling; then without_readline=yes fi #exported variables _readline_list="readline readline_version readline_enabledp CPPF_defined \ rl_library_version rl_fake_library_version rl_history rl_refresh_line_oldproto rl_appendchar rl_message \ rl_save_prompt rl_fake_save_prompt _rl_save_prompt\ rl_genericbind rl_bind_key_in_map rl_attempted_completion_over rl_completion_query_items \ rl_completion_matches rl_completion_func_t \ 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 if test -z "$without_readline"; then pth="$with_readline_lib $libpth" lib=readline; . ./locatelib rl_fullname=$try fi if test -n "$readline"; then # Readline -- Headers pth="$with_readline_include $basic_include_path" x=`./locate 'readline/readline.h' '' $pth` CPPF_defined= case $x in ?:/*|/*) rl_include=`dirname $x` echo ..."Found readline header in $rl_include" if (test -r "$rl_include/history.h"); then echo ..."Found history header in $rl_include" rl_history=yes else echo ..."No history header in $rl_include" fi if (grep CPPFunction $x > /dev/null 2>&1); then CPPF_defined=yes; fi if (grep rl_message $x > /dev/null 2>&1); then rl_message=yes; fi if (grep rl_completion_matches $x > /dev/null 2>&1); then rl_completion_matches=yes; fi if (grep rl_completion_func_t $x > /dev/null 2>&1); then rl_completion_func_t=yes; fi if (grep "rl_refresh_line *()" $x > /dev/null 2>&1); then rl_refresh_line_oldproto=yes fi if (grep rl_completion_append_character $x > /dev/null 2>&1); then rl_appendchar=yes fi if (grep rl_generic_bind $x > /dev/null 2>&1); then rl_genericbind=yes fi if (grep rl_attempted_completion_over $x > /dev/null 2>&1); then rl_attempted_completion_over=yes; fi if (grep rl_completion_query_items $x > /dev/null 2>&1); then rl_completion_query_items=yes; fi if (grep rl_bind_key_in_map $x > /dev/null 2>&1); then rl_bind_key_in_map=yes; fi if (grep rl_library_version $x > /dev/null 2>&1); then rl_library_version=yes; rl_extra_flags="-DHAS_RL_LIBRARY_VERSION" fi if (grep rl_save_prompt $x > /dev/null 2>&1); then rl_save_prompt=yes; else # might be defined but not declared (old readline) lib=$rl_fullname; sym=rl_save_prompt; . ./locatesymbol _rl_save_prompt=$try fi;; *) echo ..."But no header file has been found" readline=;; esac fi if test -n "$readline"; then pth="$libpth" # Readline -- Allocation lib=$rl_fullname; sym=alloca; . ./locatesymbol if test -n "$try"; then # alloca needed lib=iberty; . ./locatelib rl_liberty="$try" fi # Readline -- TermCap lib=$rl_fullname; sym=tgetent; . ./locatesymbol need_tgetent="$try" if test -n "$need_tgetent"; then opth=$pth; pth="$with_ncurses_lib $libpth" lib=ncurses; . ./locatelib if test -n "$try"; then # ncurses found. Does it contain tgetent ? lib=$try; . ./locatesymbol fi if test -n "$try"; then rl_ncurses=$ncurses need_tgetent= else # give termcap a try pth="$with_readline_lib $libpth" lib=termcap; . ./locatelib if test -n "$try"; then rl_termcap=$termcap need_tgetent= fi fi pth=$opth fi # Readline -- CFLAGS if (echo $rl_include | grep "readline$" > /dev/null); then rl_include=`dirname $rl_include` RLINCLUDE="-I$rl_include" fi RLLIBS="-L$readline -lreadline" if test -n "$rl_ncurses"; then echo ..."Library ncurses needed by readline" RLLIBS="$RLLIBS -L$rl_ncurses -lncurses" fi if test -n "$rl_termcap"; then echo ..."Library termcap needed by readline" RLLIBS="$RLLIBS -L$rl_termcap -ltermcap" fi if test -n "$rl_liberty"; then echo ..."Library liberty needed by readline" RLLIBS="$RLLIBS -L$rl_liberty -liberty" fi # Readline -- last chance for tgetent if test -n "$need_tgetent"; then # try to compile anyway (in libc?) list=readline; extra_flags="$RLLIBS $RLINCLUDE"; ./look if test "$has_readline" = no; then echo "cannot use readline: please install libncurses or libtermcap." readline= fi fi fi if test -n "$readline"; then exe=$osname-$arch-rlv$$ $CC $CFLAGS $extraflag $rl_extra_flags $RLINCLUDE -o $exe rl_version.c $RLLIBS 2> /dev/null if test -r $exe; then readline_version=`env LD_LIBRARY_PATH="$LD_LIBRARY_PATH$dir_sep$readline" $RUNTEST $exe`; else readline_version="?.?"; 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 detected, but does not seem to work" echo "###";; esac fi if test -n "$readline"; then if test -z "$rl_library_version"; then echo "!!! Possible mismatch between readline headers and library:" echo "!!! header is apparently for v1.0, library reports $readline_version!" case "$readline_version" in # rl_save_prompt was not in 2.1, is in 4.1; do not know more... 4.[1-9]*|[5-9]*) rl_fake_save_prompt=yes;; esac readline_version="1.0=Header/$readline_version=Lib" rl_fake_library_version=yes fi if test -z "$rl_appendchar"; then echo ..."Library readline does not have completion_append_char" fi if test -z "$rl_genericbind"; then echo ..."Library readline does not have rl_generic_bind" fi if test -z "$rl_completion_query_items"; then echo ..."Library readline does not have rl_completion_query_items" fi if test -z "$rl_bind_key_in_map"; then echo ..."Library readline does not have rl_bind_key_in_map" fi if test -z "$rl_attempted_completion_over"; then echo ..."Library readline does not have rl_attempted_completion_over" fi if test -z "$rl_save_prompt"; then echo ..."Library readline does not have rl_save_prompt" if test -n "$_rl_save_prompt"; then echo ......"but it has _rl_save_prompt" if test -n "$rl_fake_save_prompt"; then echo ........."but due to library mismatch we fake rl_save_prompt" rl_save_prompt=yes fi fi fi 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" readline_enabledp="t"; fi pari-2.5.5/config/endian.c0000644000175000017500000000067411636712103013762 0ustar billbill#include 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==(1UL<<62)) printf("-\n"); else printf("NOT IEEE (64 bit)\n"); } } pari-2.5.5/config/get_install0000644000175000017500000000400111636712103014574 0ustar billbill# Exported variables _install_list="prefix share_prefix bindir datadir includedir libdir mandir sysdatadir " dflt=$prefix; rep= test "$fastread" = yes || cat </dev/null || arch 2>&1` if test -d /NextApps; then myuname=nextstep; fi if test -n "$myuname"; then myuname=`echo $myuname | sed -e 's/^[^=]*=//' -e 's,/,,g' | \ tr '[A-Z]' '[a-z]' | tr '\012' ' '` set X $myuname; shift; osname=$1 case "$osname" in irix*) osname=irix;; fx2800) arch=fx2800; osname=concentrix;; hp*) osname=hpux; arch=`uname -m` case $arch in ia64) arch=ia64;; 9000/[34]*) arch=m68k;; 9000/[678]*) arch=hppa;; *) arch=hppa;; esac;; os2) arch=`uname -m` if test -z "$arch"; then arch=ix86; fi ;; freebsd|netbsd|openbsd) arch=`uname -m` if test -z "$arch"; then arch=ix86; fi case $arch in amd64) arch=x86_64;; esac;; cygwin*) arch=`uname -m` if test -z "$arch"; then arch=ix86; fi osname=cygwin;; mingw*) arch=`uname -m` if test -z "$arch"; then arch=ix86; fi osname=mingw;; ultrix) arch=mips;; nextstep) arch=`file /bin/sh | sed 's/.*(for architecture \(.*\))/\1/'`;; darwin*) arch=`uname -p` if test "$arch" = powerpc; then arch=ppc; fi ;; osf1) case "$5" in alpha) arch=alpha;; esac;; linux) arch=`uname -m` case $arch in sparc64) arch=sparcv9;; parisc*) arch=hppa;; sparc) case "`cat /proc/cpuinfo`" in *SuperSparc*) arch=sparcv8_super;; *TMS390Z5[05]*) arch=sparcv8_super;; # SuperSparc I or II *TMS390S1[05]*) arch=sparcv8_micro;; # MicroSparc I *MB86904*) arch=sparcv8_micro;; # MicroSparc II *MB86907*) arch=sparcv8_micro;; # TurboSparc *MB86934*) arch=sparcv8_super;; # SparcLite *RT625*) arch=sparcv8_super;; # HyperSparc *CY605*) arch=sparcv8_super;; esac;; esac;; sunos) case "$3" in 5*) osname=solaris;; esac case "$5" in sun4|sun4[ce]) ;; #arch=sparcv7;; sun4[dm]) cpu="TI,|FMI,|Cypress,|Ross," case "`(prtconf||devinfo)2>&- |egrep $cpu`" in *TI,TMS390Z5[05]*) arch=sparcv8_super;; # SuperSparc I or II *TI,TMS390S1[05]*) arch=sparcv8_micro;; # MicroSparc I *FMI,MB86904*) arch=sparcv8_micro;; # MicroSparc II *FMI,MB86907*) arch=sparcv8_micro;; # TurboSparc *FMI,MB86934*) arch=sparcv8_super;; # SparcLite *Ross,RT625*) arch=sparcv8_super;; # HyperSparc *Cypress,CY605*) arch=sparcv8_super;; *) arch=sparcv8_super;; # ??? esac;; sun4[uv]) arch=sparcv9;; i*pc) arch=ix86;; esac;; gnu*) # Cover GNU/Hurd, GNU/kFreeBSD and other GNU userland arch=`uname -m`; case $arch in i386-*) arch=i386;;esac;; aix) arch=`uname -p`; case $arch in powerpc) arch=ppc;;esac;; esac fi echo $arch-$osname pari-2.5.5/config/get_fltk0000644000175000017500000000123112147140046014067 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" else echo "### FLTK not found. Building without FLTK support" fi case "$osname" in cygwin) FLTK_LIBS="-lgdi32 -lole32 -luuid -lwsock32 -lsupc++" ;; darwin) FLTK_LIBS="-framework Carbon -lsupc++" ;; *) FLTK_LIBS="$X11_LIBS" ;; esac pari-2.5.5/config/get_nl0000644000175000017500000000043711636712103013550 0ustar billbillecho "Checking echo to see how to suppress newlines..." if (echo "hi\c"; echo " ") | grep c >/dev/null 2>&1 ; then echo "...using -n."; n=-n; c= else cat <$c"; echo '*' fi pari-2.5.5/config/checkspaces0000755000175000017500000000077312147140046014561 0ustar billbill#! /bin/sh CFILES="`echo src/*/*.[chy] src/*/*/*.[ch] examples/*.c examples/*.gp |sed -e 's,src/language/parse\.[ch],,g'`" OFILES="AUTHORS COMPAT NEW TODO CHANGES MACHINES doc/*.tex src/test/in/* src/functions/*/*" SCRIPTS="config/* src/test/dotest" err=0; if grep ' $' $CFILES $OFILES $SCRIPTS; 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.5.5/config/paricfgDOS.h.SH0000644000175000017500000000360012147140046015012 0ustar billbillfile="$objdir/../Odos/paricfg.h"; echo Extracting $file rm -f $file cat > $file << EOT /* This file extracted by Configure. */ #ifndef __CONFIG_H__ #define __CONFIG_H__ #ifdef _MSC_VER /* Bill Daly: avoid spurious Warnings from MSVC */ # pragma warning(disable: 4013 4018 4146 4244 4761) #endif #define GPDATADIR "/pari/data" #define SHELL_Q '"' #define DL_DFLT_NAME "libpari.dll" #define PARIVERSION "GP/PARI CALCULATOR Version ${version}.${patch} (${status})" #if defined(__EMX__) # define PARIINFO "ix86 running EMX (ix86 kernel) 32-bit version" #endif #if defined(WINCE) # define PARIINFO "Windows CE 32-bit version" #endif #if !defined(PARIINFO) # define PARIINFO "ix86 running Windows 3.2 (ix86 kernel) 32-bit version" #endif #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_DOUBLE_FORMAT 1 #ifdef _MSC_VER /* MSVC inline directive */ # define INLINE __inline #endif /* Location of GNU gzip program, enables reading of .Z and .gz files. */ #ifndef WINCE # define GNUZCAT # define ZCAT "gzip -d -c" #endif #ifdef __EMX__ # define STACK_CHECK # define READLINE # define HAS_RL_MESSAGE # define CPPFunction_defined /* in readline 1, no arguments for rl_refresh_line() */ # define RL_REFRESH_LINE_OLDPROTO #endif #ifdef __MINGW32__ # define READLINE "4.0" # define HAS_COMPLETION_APPEND_CHAR # define HAS_RL_SAVE_PROMPT # define HAS_RL_MESSAGE # define CPPFunction_defined #endif #if defined(__EMX__) || defined(_WIN32) # define HAS_ISATTY #endif /* No exp2, log2 in libc */ #define NOEXP2 #if !defined(WINCE) && !(defined(_WIN32) && defined(_MSC_VER)) /* Timings: Don't use times because of the HZ / CLK_TCK confusion. */ # define USE_FTIME 1 # define HAS_STRFTIME #endif #if defined(_WIN32) && defined(_MSC_VER) # define HAS_STAT #endif #endif EOT pari-2.5.5/config/get_PATH0000644000175000017500000000135711636712103013675 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.5.5/config/has_setsid.c0000644000175000017500000000014411636712103014642 0ustar billbill#include #include pid_t (*f)() = setsid; int main(){ return f != setsid; } pari-2.5.5/config/install0000755000175000017500000000060011636712103013741 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.5.5/config/get_double_format0000644000175000017500000000320211636712103015752 0ustar billbillexe=$osname-$arch-endian$$ if ($CC $CFLAGS $extraflag endian.c -o $exe 2>/dev/null); 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 < /dev/null`;; *) ok=`(ls $base.* | ${head}1) 2> /dev/null` if test -n "$ok"; then _pb="$ok" # so, sl, dylib, dll.a try=`ls $base.s? $base.a $base.dylib $base.dll.a 2> /dev/null` else try= fi;; esac if test -n "$try"; then echo ..."Found lib$lib in $dir"; eval $lib=$dir; break fi done # not found? detect missing lib*.so (missing *-devel package) if test -z "$try"; then if test "$osname" = linux -a -n "$_pb"; then case "$lib" in X11) rpmlib="[XFree86|xorg-x11|libx11]"; devlib=libx11 ;; *) rpmlib=$lib; devlib=lib$lib ;; esac echo "###" echo "### lib$lib.so not found. Please install $lib development files." echo "### They usually come in $rpmlib-devel (RPM) or $devlib-dev (Debian) packages" echo "###" fi fi pari-2.5.5/config/get_objdir0000644000175000017500000000156511636712103014413 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 ;; 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.5.5/config/settar0000755000175000017500000000154512147140046013605 0ustar billbill#!/bin/sh dir=$1; status=$2; # true status (probably 'development') STATUS=$3; # status we're being coerced into extrafile= case "$STATUS" in alpha|beta) dir="$dir.$STATUS";; snapshot) STATUS=development; extrafile=config/gitversion; git describe > config/gitversion; dir=`cat config/gitversion`;; esac tarfile=$dir.tar v='config/version' if test "$status" != "$STATUS"; then mv $v $v.old sed -e "s/status=.*/status=$STATUS/" $v.old > $v tar cf $tarfile `config/get_MANIFEST` $extrafile mv $v.old $v else tar cf $tarfile `config/get_MANIFEST` $extrafile fi if test -d $dir; then echo "Remove $dir before building a new release"; exit 1 fi mkdir $dir && mv $tarfile $dir cd $dir && tar xf $tarfile && rm -f $tarfile && cd .. tar cf $tarfile $dir rm -f config/gitversion rm -rf $dir rm -f $tarfile.gz gzip $tarfile pari-2.5.5/Configure0000755000175000017500000001276712147140046012767 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` 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 ... list='ld zcat gzip ranlib perl' pathspace=`echo $PATH | sed -e "s/$dir_sep/ /g" | sed -e 's,\\\\,/,g'` for file in $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 ####################### CONFIGURE - COMPILATION ############################# # $_cc_list (includes 'optimization'), extraflag . ./get_cc # 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, 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 . ./get_gmp # $_graphic_list . ./get_graphic_lib # $_readline_list (includes 'readline') . ./get_readline ############################################################################# 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 ####################### 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 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 DL_LIBS LIBS\ dir_sep runpath runpathprefix LDDYN RUNTEST\ ranlib gzip zcat perl ln_s make_sh\ sizeof_long doubleformat\ enable_tls\ $_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 # 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;\ 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 !'